26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
54 #pragma package(smart_init)
73 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
74 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
75 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
76 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
77 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
78 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
89 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
90 AnsiString(TrainModeIn));
137 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
155 for(
int x = 0; x < 4; x++)
160 for(
int x = 0; x < 4; x++)
164 for(
int x = 0; x < 3; x++)
202 for(
int x = 0; x < 4; x++)
283 throw Exception(
"Error in attempting to delete FrontCodePtr");
287 for(
int x = 0; x < 4; x++)
291 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
296 for(
int x = 0; x < 4; x++)
300 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
335 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
401 bool TempDerail =
false;
447 else if((NextElementPosition > -1) && (NextEntryPos > -1))
518 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
528 for(
int x = 0; x < 4; x++)
535 for(
int x = 0; x < 4; x++)
802 int LockedVectorNumber;
931 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
932 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
933 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
934 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
935 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
936 "of a shortage of on train crew"};
952 int randval = random(10000);
957 if(randval < Utilities->MinorDelayCutoff)
964 if(randval < Utilities->ModerateDelayCutoff)
971 if(randval < Utilities->MajorDelayCutoff)
986 if(
NewDelay <
double(DwellTime) * 1440)
992 NewDelay -= double(DwellTime) * 1440;
1058 int randval2 = rand() % 24;
1059 AnsiString Reason = ReasonArray[randval2];
1062 " minutes because " + Reason);
1064 " minutes because " + Reason);
1070 " minutes because of a minor problem");
1072 " minutes because of a minor problem");
1238 if(BufferLocation ==
"")
1243 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1305 int NextElementPosition, NextEntryPos;
1329 NextElementPosition = -1;
1332 if((NextElementPosition > -1) && (NextEntryPos > -1))
1481 AnsiString StationName;
1492 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1502 if((NextElementPosition > -1) && (NextEntryPos > -1))
1653 if(TIFEntryPos == 0)
1690 if(NextElementPosition > -1)
1727 AnsiString Loc =
"";
1728 bool LocNamed =
false;
1757 Loc =
"outside railway";
1789 NextElementPosition = -1;
1800 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1818 if((NextElementPosition > -1) && (NextEntryPos > -1))
1856 FirstPair.second).
GetELink() == TempELink))
1861 SecondPair.second).
GetELink() == TempELink))
1875 FirstPair.second).
GetELink() == TempELink))
1880 SecondPair.second).
GetELink() == TempELink))
1894 FirstPair.second).
GetELink() == TempELink))
1899 SecondPair.second).
GetELink() == TempELink))
1929 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1932 int NewLastElement = 0, NewLastExitPos = 0;
1950 if(NewLastElement == -1)
1956 if(NewLastExitPos == -1)
1960 LastElement = NewLastElement;
1961 LastExitPos = NewLastExitPos;
1964 if(CumDistance < 1200)
1970 int FirstDistance = 0;
1971 if(CumDistance >= 1200)
1973 FirstDistance = 100;
1977 FirstDistance = 1200 - CumDistance;
1979 if(FirstDistance < 100)
1981 FirstDistance = 100;
2007 if(VectorIT->RouteNumber == RouteNumber)
2044 " failed when changing aspect.\nTrains can only pass under signaller control.");
2078 LockedVectorNumber)))
2237 for(
int x = 0; x < 4; x++)
2244 for(
int x = 0; x < 4; x++)
2270 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2275 if(OtherTrainEntryPos == -1)
2277 throw Exception(
"Error - OtherTrainEntryPos not set");
2296 int OtherTrainID = -1;
2297 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2388 bool StopRequired =
false;
2403 int NextElementEntryPos = -1;
2404 int NextElementExitPos = -1;
2405 bool TrainOnNextElement =
false;
2406 bool StopSignalAtNextElement =
false;
2407 if(ForwardConnection)
2415 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2417 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2478 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2542 int VPos, HPos, TrainHLocLead, TrainHLocMid, TrainHLocLag, TrainVLocLead, TrainVLocMid, TrainVLocLag;
2544 bool ReturnEarly =
false;
2577 int LeftHAndOffset, TopVAndOffset;
2582 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2583 if(((TrainLead.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2585 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[1];
2587 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2589 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2591 if(((TrainMid.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2593 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[3];
2595 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2596 if(((TrainLead.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2598 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[1];
2600 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2602 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2604 if(((TrainMid.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2606 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[3];
2608 HPos = LeftHAndOffset;
2609 VPos = TopVAndOffset - 10;
2613 LeftHAndOffset = (TrainLead.
HLoc * 16) +
HOffset[0];
2614 if(((TrainMid.
HLoc * 16) +
HOffset[1]) < LeftHAndOffset)
2616 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[1];
2618 if(((TrainMid.
HLoc * 16) +
HOffset[2]) < LeftHAndOffset)
2620 LeftHAndOffset = (TrainMid.
HLoc * 16) +
HOffset[2];
2622 if(((TrainLag.
HLoc * 16) +
HOffset[3]) < LeftHAndOffset)
2624 LeftHAndOffset = (TrainLag.
HLoc * 16) +
HOffset[3];
2626 TopVAndOffset = (TrainLead.
VLoc * 16) +
VOffset[0];
2627 if(((TrainMid.
VLoc * 16) +
VOffset[1]) < TopVAndOffset)
2629 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[1];
2631 if(((TrainMid.
VLoc * 16) +
VOffset[2]) < TopVAndOffset)
2633 TopVAndOffset = (TrainMid.
VLoc * 16) +
VOffset[2];
2635 if(((TrainLag.
VLoc * 16) +
VOffset[3]) < TopVAndOffset)
2637 TopVAndOffset = (TrainLag.
VLoc * 16) +
VOffset[3];
2639 HPos = LeftHAndOffset;
2640 VPos = TopVAndOffset - 10;
2683 for(
int x = 3; x < 13; x++)
2688 for(
int y = 0; y < 54; y++)
2692 SLPtrOut[y] = SLPtrIn[y];
2693 SLPtrImage[y] = 0x01;
2717 for(
int x = 3; x < 13; x++)
2721 for(
int y = 0; y < 54; y++)
2753 Graphics::TBitmap *TempBitmap =
new Graphics::TBitmap;
2754 TempBitmap->PixelFormat = pf8bit;
2755 TempBitmap->Height = 10;
2756 TempBitmap->Width = 54;
2763 for(
int x = 0; x < 10; x++)
2765 SLPtrIn =
reinterpret_cast<Byte*
>(TempBitmap->ScanLine[x]);
2767 for(
int y = 0; y < 54; y++)
2769 if(SLPtrIn[y] == 0xac)
2773 else if(SLPtrIn[y] == 0xb4)
2777 else if(SLPtrIn[y] == 0x05)
2993 if(Code.Length() != 4)
2997 for(
int x = 1; x < 5; x++)
3004 for(
int x = 0; x < 4; x++)
3167 throw Exception(
"Error in GetOffsetValues - Link value wrong");
3180 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
3195 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
3204 TRect SourceRect, DestRect;
3206 DestRect.init(0, 0, 8, 8);
3209 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
3211 TempGraphic->PixelFormat = pf8bit;
3212 TempGraphic->Width = 16;
3213 TempGraphic->Height = 16;
3219 TempGraphic->Transparent =
true;
3223 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3224 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3230 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3238 else if(TempElement.
SpeedTag == 89)
3242 else if(TempElement.
SpeedTag == 90)
3246 else if(TempElement.
SpeedTag == 91)
3250 else if(TempElement.
SpeedTag == 92)
3254 else if(TempElement.
SpeedTag == 93)
3258 else if(TempElement.
SpeedTag == 94)
3262 else if(TempElement.
SpeedTag == 95)
3266 TempGraphic->Transparent =
true;
3270 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3271 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3273 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3280 for(
int x = 0; x < 40; x++)
3295 TempGraphic->Transparent =
true;
3299 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3300 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3302 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3316 TempGraphic->Transparent =
true;
3320 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3321 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3325 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
3328 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3333 TempGraphic->Transparent =
true;
3337 int BDVectorPos = -1;
3346 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3351 TempGraphic->Transparent =
true;
3355 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3356 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3358 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3364 TempGraphic->Transparent =
true;
3368 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
3369 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3371 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3637 throw Exception(
"Error, same train on two different bridge tracks");
3683 AnsiString(EntryPos) +
"," +
HeadCode);
3700 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3719 AnsiString(EntryPos) +
"," +
HeadCode);
3728 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3761 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3762 int LockedVectorNumber;
3775 TRect SourceRect, DestRect;
3776 DestRect.init(0, 0, 8, 8);
3783 int FirstELink, SecondELink = -1;
3786 if(RoutePair2.first > -1)
3795 if(SecondELink == -1)
3797 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3802 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3812 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3813 DestGraphic->PixelFormat = pf8bit;
3814 DestGraphic->Width = 8;
3815 DestGraphic->Height = 8;
3816 DestGraphic->Transparent =
true;
3819 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3828 PrefDirElement, LockedVectorNumber))
3843 if(ElementEntryPos > 1)
3865 AnsiString(EntryPos) +
"," +
HeadCode);
3867 bool WrongRoute =
false;
3893 int LinkNumber = TrackElement.
Link[EntryPos];
3894 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3899 bool LogActionErrorCalled =
false;
3909 LogActionErrorCalled =
true;
3926 else if(LinkNumber == 3)
3934 LogActionErrorCalled =
true;
3951 else if(LinkNumber == 7)
3959 LogActionErrorCalled =
true;
3976 else if(LinkNumber == 9)
3984 LogActionErrorCalled =
true;
4016 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
4021 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4031 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
4036 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
4045 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
4066 bool ColourError =
false, ColourError2 =
false;
4071 ColourError2 =
true;
4073 for(
int x = 0; x < 4; x++)
4078 ColourError2 =
true;
4084 "256 colours can be displayed");
4088 for(
int x = 0; x < 4; x++)
4175 AnsiString(EntryPos) +
"," +
HeadCode);
4176 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
4177 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
4178 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
4179 TrainInFrontInSignallerModeFlag =
false;
4180 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
4181 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
4182 bool SignallerStopRequired =
false;
4196 if(CurrentTrackVectorPosition > -1)
4200 if((EntryPos == 0) || (EntryPos == 2))
4213 else if(EntryPos == 1)
4237 EntryHalfLength = CurrentElementHalfLength;
4242 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
4246 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
4294 FrontElementMaxSpeed = LimitingSpeed;
4330 double ExitSpeedAtMaxBraking;
4335 ExitSpeedAtMaxBraking = 0;
4345 if(ExitSpeedAtMaxBraking > LimitingSpeed)
4347 SpeedToUse = ExitSpeedAtMaxBraking;
4351 SpeedToUse = LimitingSpeed;
4366 RedSignalFlag =
false;
4367 BuffersFlag =
false;
4368 StationFlag =
false;
4369 BuffersOrContinuationNowFlag =
false;
4370 ContinuationNextFlag =
false;
4373 CumulativeLength += (2 * CurrentElementHalfLength);
4376 SignallerStopRequired =
true;
4398 bool StopRequired =
false;
4414 StationFlag =
false;
4420 BuffersOrContinuationNowFlag =
true;
4422 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4426 if((EntryPos == 0) || (EntryPos == 2))
4448 if(NextTrackVectorPosition > -1)
4453 if((NextEntryPos == 0) || (NextEntryPos == 2))
4466 else if(NextEntryPos == 1)
4479 if(NextEntryPos > 1)
4493 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4505 RedSignalFlag =
true;
4526 TrainInFrontInSignallerModeFlag =
true;
4551 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4563 double MaxHalfSpeed;
4567 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4569 MaxHalfSpeed = FrontElementMaxSpeed;
4573 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4581 bool HalfSpeedLimited =
false;
4585 HalfSpeedLimited =
true;
4615 if(HalfSpeedLimited)
4640 if(SignallerStopRequired)
4656 int TempMaxExitSpeed;
4659 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4661 MaxExitSpeedAtHalfBraking = 0;
4665 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4669 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4671 TempMaxExitSpeed = FrontElementMaxSpeed;
4675 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4687 if(ExitSpeedHalfSquared < 10)
4697 if(ExitSpeedFullSquared < 10)
4769 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4770 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4794 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4795 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4805 if(!BuffersOrContinuationNowFlag)
4807 if(NextSpeedLimit < LimitingSpeed)
4809 LimitingSpeed = NextSpeedLimit;
4813 int TempMaxExitSpeed;
4817 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4819 MaxExitSpeedAtHalfBraking = 0;
4823 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4825 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4827 TempMaxExitSpeed = FrontElementMaxSpeed;
4831 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4842 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4855 if(!BuffersOrContinuationNowFlag)
4857 CurrentTrackVectorPosition = NextTrackVectorPosition;
4858 EntryPos = NextEntryPos;
4859 CurrentElementHalfLength = NextElementHalfLength;
4862 ContinuationNextFlag =
true;
4866 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4886 if(ExitSpeedHalfSquared < 10)
4896 if(ExitSpeedFullSquared < 10)
4959 double DeltaExitTimeToMaxInSecs;
4960 double DistanceToMax;
4969 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4971 DistanceToMax = EntryHalfLength;
4974 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4975 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4992 double DeltaExitTimeToMaxInSecs;
4993 double DistanceToMax;
5002 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
5004 DistanceToMax = EntryHalfLength / 2;
5007 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
5008 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
5019 if(ExitSpeedHalfSquared < 10)
5029 if(ExitSpeedFullSquared < 10)
5048 if((EntryPos == 0) || (EntryPos == 2))
5070 if(NextTrackVectorPosition > -1)
5072 int NextElementLength;
5073 if(NextEntryPos > 1)
5081 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
5277 int ElementCount = 0;
5285 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
5343 if((EntryPos == 0) || (EntryPos == 2))
5365 CurrentTrackVectorPosition = NextTrackVectorPosition;
5366 EntryPos = NextEntryPos;
5368 if(ElementCount > 1000)
5396 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5421 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5422 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5423 int RouteStartPosition;
5425 int PlatformPosition;
5427 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5443 if(Distance > (4000 + LeadElementDistance))
5466 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5469 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5515 if(!PlatformFoundFlag)
5517 PlatformPosition = CurrentTrackVectorPosition;
5520 PlatformFoundFlag =
true;
5536 if((EntryPos == 0) || (EntryPos == 2))
5580 if(ElementNumber < 2)
5582 SkipRouteCheck =
true;
5586 SkipRouteCheck =
false;
5588 if(ElementNumber == 1)
5590 RouteStartPosition = CurrentTrackVectorPosition;
5600 if(ElementNumber > 1)
5604 RouteOrPartRouteSet =
true;
5608 RouteOrPartRouteSet =
false;
5611 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5618 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5619 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5631 Distance += CurrentTrackElement.
Length01;
5635 Distance += CurrentTrackElement.
Length23;
5637 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5638 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5639 CurrentTrackVectorPosition = NextTrackVectorPosition;
5640 EntryPos = NextEntryPos;
5677 return(RepeatHeadCode);
5699 bool FrontValid =
false, RearValid =
false;
5700 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5704 TrainToBeJoinedBy = NULL;
5718 int TrainToBeJoinedByID = -1;
5739 if((TrainToBeJoinedByID < 0) && RearValid)
5758 if(TrainToBeJoinedByID < 0)
5760 TrainToBeJoinedBy = NULL;
5765 if(!TrainToBeJoinedBy->
Stopped())
5767 TrainToBeJoinedBy = NULL;
5777 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5778 TDateTime TimetableNonRepeatTime,
bool Warning)
5815 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5816 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5817 int IntMinsLate = 0;
5818 bool TTEvent =
false;
5823 ActionLog =
" arrived at ";
5833 ActionLog =
" terminated at ";
5839 ActionLog =
" departed from ";
5842 if(ActionType ==
Pass)
5844 ActionLog =
" passed ";
5849 ActionLog =
" created at ";
5851 if(ActionType ==
Enter)
5853 ActionLog =
" entered railway at ";
5857 ActionLog =
" changed its description to '" +
Description +
"' at ";
5865 if(ActionType ==
Leave)
5867 ActionLog =
" left railway at ";
5872 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5877 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5882 ActionLog =
" joined by ";
5887 ActionLog =
" changed direction at ";
5892 ActionLog =
" became new service ";
5897 ActionLog =
" taken under signaller control at ";
5901 ActionLog =
" restored to timetable control at ";
5907 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5911 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5915 ActionLog =
" REMOVED FROM RAILWAY at ";
5920 ActionLog =
" received signaller authority to proceed";
5924 ActionLog =
" received signaller authority to step forward";
5928 ActionLog =
" changed direction under signaller control at ";
5932 ActionLog =
" received signaller authority to pass stop signal";
5936 ActionLog =
" received signaller instruction to stop";
5940 ActionLog =
" stopped on signaller instruction ";
5944 ActionLog =
" joined under signaller control by ";
5948 ActionLog =
" suffered an onboard power failure at ";
5952 ActionLog =
" failure repaired at ";
5956 ActionLog =
" left railway under signaller control at ";
5958 if(OtherHeadCode !=
"")
5960 OtherHeadCode +=
" at ";
5992 bool TimePerformance =
true;
5993 AnsiString MinMinsString =
"";
6000 TimePerformance =
false;
6004 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
6006 if(ActionType ==
Pass)
6020 IntMinsLate = int(ceil(MinsLate));
6024 IntMinsLate = int(floor(MinsLate));
6026 if(IntMinsLate == 0)
6028 PerfLog =
" on time";
6030 else if(IntMinsLate == 1)
6032 PerfLog =
" 1 minute late";
6034 else if(IntMinsLate == -1)
6036 PerfLog =
" 1 minute early";
6038 else if(IntMinsLate > 1)
6040 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
6042 else if(IntMinsLate < -1)
6044 int PosIntMinsLate = -IntMinsLate;
6045 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
6047 if(LocationName.Pos(
'-') > 0)
6049 PerfLog =
"," + PerfLog;
6055 double MDT = int(MDTdouble * 10);
6057 MinMinsString =
"mins";
6058 if((MDT < 1.1) && (MDT > 0.9))
6060 MinMinsString =
"min";
6077 if(ReminderBaseLog !=
"")
6080 ReminderBaseLog =
"";
6084 if((ActionType ==
Arrive) && (IntMinsLate == 0))
6088 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
6093 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
6099 else if((ActionType ==
Pass) && (IntMinsLate == 0))
6103 else if((ActionType ==
Pass) && (IntMinsLate > 0))
6108 else if((ActionType ==
Pass) && (IntMinsLate < 0))
6114 else if((ActionType ==
Leave) && (IntMinsLate == 0))
6118 else if((ActionType ==
Leave) && (IntMinsLate > 0))
6123 else if((ActionType ==
Leave) && (IntMinsLate < 0))
6129 else if((ActionType ==
Depart) && (IntMinsLate == 0))
6133 else if((ActionType ==
Depart) && (IntMinsLate > 0))
6152 AnsiString LocName =
"";
6225 if(LocationName ==
"")
6229 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
6230 int FrontTrainRearPos, FrontTrainFrontPos;
6233 if(LocationName ==
"")
6235 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
6239 bool TemporaryDelay =
false;
6241 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6265 AnsiString SplittingTrainDescription =
Description;
6272 for(
int x = 0; x < 4; x++)
6292 double NewTrainPowerAtRail;
6298 NewTrainMass =
Mass * double(MassPercent)/100.0;
6300 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6301 if(NewTrainPowerAtRail == 0)
6303 NewTrainPowerAtRail = 0.08;
6311 NewTrainMass =
Mass;
6339 if(!SplitTrainExplicitDescription)
6386 if(LocationName ==
"")
6390 int RearTrainRearPos, RearTrainFrontPos;
6391 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
6394 if(LocationName ==
"")
6396 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6400 bool TemporaryDelay =
false;
6402 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6426 AnsiString SplittingTrainDescription =
Description;
6433 for(
int x = 0; x < 4; x++)
6453 double NewTrainPowerAtRail;
6459 NewTrainMass =
Mass * double(MassPercent)/100.0;
6461 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6462 if(NewTrainPowerAtRail == 0)
6464 NewTrainPowerAtRail = 0.08;
6472 NewTrainMass =
Mass;
6500 if(!SplitTrainExplicitDescription)
6594 TTrain *TrainToBeJoinedBy;
6638 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6640 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6708 int RouteNumber = -1;
6713 int CorrectRouteID = OR.
RouteID;
6719 bool FirstPass =
true;
6724 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6859 for(
int x = 0; x < IncNum; x++)
6892 else if(Ptr->
Command ==
"jbo")
6897 else if(Ptr->
Command ==
"dsc")
6902 else if(Ptr->
Command ==
"cms")
6913 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6919 bool IncludeFER =
false;
6927 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6932 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6943 else if(Ptr->
Command ==
"Fjo")
6949 else if(Ptr->
Command ==
"Frh")
6959 else if(Ptr->
Command ==
"Frh-sh")
7010 else if(Ptr->
Command ==
"jbo")
7015 else if(Ptr->
Command ==
"dsc")
7020 else if(Ptr->
Command ==
"cms")
7025 else if(Ptr->
Command ==
"cdt")
7033 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7455 int RouteNumber = -1;
7460 int CorrectRouteID = OR.
RouteID;
7466 bool FirstPass =
true;
7471 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7499 ",FloatingLabelNextString" +
"," +
HeadCode);
7500 AnsiString RetStr =
"", LocationName =
"";
7503 if(ActionTime == TDateTime(-1))
7507 if(ActionTime == TDateTime(-1))
7513 if(ActionTime != TDateTime(-1))
7521 throw Exception(
"Error - start entry in FloatingLabelNextString");
7565 else if(Ptr->
Command ==
"Fns")
7571 else if(Ptr->
Command ==
"F-nshs")
7602 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7604 else if(Ptr->
Command ==
"Frh")
7606 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7608 else if(Ptr->
Command ==
"Fer")
7610 AnsiString AllowedExits =
"";
7613 else if(Ptr->
Command ==
"Fjo")
7618 else if(Ptr->
Command ==
"jbo")
7623 else if(Ptr->
Command ==
"fsp")
7628 else if(Ptr->
Command ==
"rsp")
7633 else if(Ptr->
Command ==
"cdt")
7637 else if(Ptr->
Command ==
"dsc")
7641 else if(Ptr->
Command ==
"cms")
7650 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7694 else if(Ptr->
Command ==
"Fns")
7700 else if(Ptr->
Command ==
"F-nshs")
7731 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7733 else if(Ptr->
Command ==
"Frh")
7735 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7737 else if(Ptr->
Command ==
"Fer")
7739 AnsiString AllowedExits =
"";
7742 else if(Ptr->
Command ==
"Fjo")
7747 else if(Ptr->
Command ==
"jbo")
7752 else if(Ptr->
Command ==
"fsp")
7757 else if(Ptr->
Command ==
"rsp")
7762 else if(Ptr->
Command ==
"cdt")
7766 else if(Ptr->
Command ==
"dsc")
7770 else if(Ptr->
Command ==
"cms")
7779 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7823 else if(Ptr->
Command ==
"Fns")
7829 else if(Ptr->
Command ==
"F-nshs")
7860 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7862 else if(Ptr->
Command ==
"Frh")
7864 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7866 else if(Ptr->
Command ==
"Fer")
7868 AnsiString AllowedExits =
"";
7871 else if(Ptr->
Command ==
"Fjo")
7876 else if(Ptr->
Command ==
"jbo")
7881 else if(Ptr->
Command ==
"fsp")
7886 else if(Ptr->
Command ==
"rsp")
7891 else if(Ptr->
Command ==
"cdt")
7895 else if(Ptr->
Command ==
"dsc")
7899 else if(Ptr->
Command ==
"cms")
8043 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
8044 AnsiString DepTime =
"", EventTime =
"";
8045 bool CDTFlag =
false;
8047 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
8048 AnsiString TowardsLocation =
"";
8051 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
8053 TowardsLocation = AVI->LocationName;
8055 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
8064 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
8071 if(AVI->Command ==
"cdt")
8076 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
8091 RetStr +=
"\nNew service splits at approx. " + EventTime;
8095 if(AVI->Command ==
"jbo")
8114 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
8129 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
8133 if(AVI->Command ==
"Fjo")
8152 if(AVI->Command ==
"Frh")
8154 RetStr +=
"\nNew service finishes and remains at the location.";
8158 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
8165 if(TowardsLocation !=
"")
8167 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
8171 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
8176 if(TowardsLocation !=
"")
8178 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
8182 RetStr +=
"\nNew service departs at " + DepTime;
8191 if(TowardsLocation !=
"")
8193 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8197 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8202 if(TowardsLocation !=
"")
8204 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8208 RetStr +=
"\nNew service departs at approx. " + DepTime;
8225 if(TowardsLocation !=
"")
8227 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8231 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8236 if(TowardsLocation !=
"")
8238 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8242 RetStr +=
"\nNew service departs at approx. " + DepTime;
8261 ",FloatingTimetableString" +
"," +
HeadCode);
8262 AnsiString RetStr =
"", PartStr =
"";
8264 bool SkipDep =
false, SkipDepActedOn =
false;
8266 AnsiString MinMinsString =
"";
8271 throw Exception(
"Error - start entry in FloatingTimetableString");
8274 bool FirstPass =
true;
8280 AnsiString TrainLoc =
"";
8303 double MDT = int(MDTdouble * 10);
8305 MinMinsString =
"mins";
8306 if((MDT < 1.1) && (MDT > 0.9))
8308 MinMinsString =
"min";
8322 double MDT = int(MDTdouble * 10);
8324 MinMinsString =
"mins";
8325 if((MDT < 1.1) && (MDT > 0.9))
8327 MinMinsString =
"min";
8355 double MDT = int(MDTdouble * 10);
8357 MinMinsString =
"mins";
8358 if((MDT < 1.1) && (MDT > 0.9))
8360 MinMinsString =
"min";
8374 double MDT = int(MDTdouble * 10);
8376 MinMinsString =
"mins";
8377 if((MDT < 1.1) && (MDT > 0.9))
8379 MinMinsString =
"min";
8395 AnsiString TrainLoc =
"";
8409 double MDT = int(MDTdouble * 10);
8411 MinMinsString =
"mins";
8412 if((MDT < 1.1) && (MDT > 0.9))
8414 MinMinsString =
"min";
8428 double MDT = int(MDTdouble * 10);
8430 MinMinsString =
"mins";
8431 if((MDT < 1.1) && (MDT > 0.9))
8433 MinMinsString =
"min";
8451 double MDT = int(MDTdouble * 10);
8453 MinMinsString =
"mins";
8454 if((MDT < 1.1) && (MDT > 0.9))
8456 MinMinsString =
"min";
8482 else if(Ptr->
Command ==
"Fns")
8488 else if(Ptr->
Command ==
"F-nshs")
8521 else if(Ptr->
Command ==
"Frh")
8525 else if(Ptr->
Command ==
"Fer")
8527 AnsiString AllowedExits =
"";
8530 else if(Ptr->
Command ==
"Fjo")
8535 else if(Ptr->
Command ==
"jbo")
8540 else if(Ptr->
Command ==
"fsp")
8550 PartStr+=
", split mass%-Power% = 50-50";
8553 else if(Ptr->
Command ==
"rsp")
8563 PartStr+=
", split mass%-Power% = 50-50";
8566 else if(Ptr->
Command ==
"cdt")
8570 else if(Ptr->
Command ==
"dsc")
8574 else if(Ptr->
Command ==
"cms")
8580 RetStr = RetStr +
'\n' + PartStr;
8594 SkipDepActedOn =
true;
8605 RetStr =
"Timetable finished";
8609 RetStr =
"No timetable";
8613 return(
"Timetable:\n" + RetStr);
8766 bool ForwardHeadCode;
8770 ForwardHeadCode =
true;
8775 ForwardHeadCode =
false;
8918 if(ColourNumber == 0)
8922 else if(ColourNumber == 1)
8926 else if(ColourNumber == 2)
8930 else if(ColourNumber == 3)
8934 else if(ColourNumber == 4)
8938 else if(ColourNumber == 5)
8942 else if(ColourNumber == 6)
8946 else if(ColourNumber == 7)
8950 else if(ColourNumber == 8)
8954 else if(ColourNumber == 9)
8958 else if(ColourNumber == 10)
8962 else if(ColourNumber == 11)
8966 else if(ColourNumber == 12)
8970 else if(ColourNumber == 13)
8974 else if(ColourNumber == 14)
8986 for(
int x = 0; x < 4; x++)
8993 for(
int x = 0; x < 4; x++)
9078 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
9081 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
9082 bool GiveMessagesFalse =
false;
9083 bool CheckLocationsExistInRailwayTrue =
true;
9090 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
9093 if(Marker[6] ==
'1')
9558 bool HideFlashingTrain =
true;
9561 Graphics::TBitmap *SmallTrainBitmap;
9602 HideFlashingTrain =
false;
9607 HideFlashingTrain =
false;
9612 HideFlashingTrain =
false;
9617 HideFlashingTrain =
false;
9622 HideFlashingTrain =
false;
9626 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9630 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9654 for(
int y = 0; y < 3; y++)
9658 bool FoundFlag =
false;
9669 if(IMPair.first != IMPair.second)
9696 if((LocationName ==
"") && (
MidElement > -1))
9700 if((LocationName ==
"") && (
LagElement > -1))
9704 if(LocationName ==
"")
9706 throw Exception(
"Error - Location name not set in TrainAtLocation");
9717 for(
int x = 0; x < 4; x++)
9730 for(
int x = 0; x < 4; x++)
9751 AnsiString(LinkNumber) +
"," +
HeadCode);
9803 int DistanceToRedSignal = 0, DistanceToExit = -1;
9804 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9808 float MinsEarly = 0;
9809 TDateTime DepartureTime;
9810 TDateTime ArrivalTime;
9838 if(TempTTE < LastTimeToExit)
9873 if(TempTTE < LastTimeToExit)
9896 if(TempTTE < LastTimeToExit)
9926 if(TempTTE < LastTimeToExit)
9949 if(TempTTE < LastTimeToExit)
9992 float CurrentStopTime;
9993 float LaterStopTime;
9994 float RecoverableTime;
10002 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
10009 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
10010 bool DistanceToExitSet = (DistanceToExit > -1);
10011 int GenericDistance = DistanceToRedSignal;
10012 if(DistanceToExitSet)
10014 GenericDistance = DistanceToExit;
10030 float TimeToSubtract, TotalStopTime;
10033 TimeToSubtract = RecoverableTime;
10076 if(CurrentStopTime > 0)
10078 TotalStopTime = CurrentStopTime + LaterStopTime;
10087 else if((MinsEarly > 0) && !
Stopped())
10089 TotalStopTime = LaterStopTime + MinsEarly;
10093 if(LaterStopTime == 0)
10095 TotalStopTime = CurrentStopTime;
10101 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
10104 if(AvTrackSpeed < 30)
10108 int Speed = AvTrackSpeed;
10118 if(DistanceToRedSignalSet)
10120 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
10130 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
10159 if((NextEntryPos == 0) || (NextEntryPos == 2))
10317 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10356 if(AVEntry0.
Command ==
"Snt")
10360 int IncrementalMinutes = 0;
10361 int IncrementalDigits = 0;
10369 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10405 if(AVEntry0.
Command ==
"Snt-sh")
10410 int IncrementalMinutes = 0;
10411 int IncrementalDigits = 0;
10419 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10463 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10543 AnsiString Loc =
"";
10544 bool ElementFound =
false;
10549 ElementFound =
true;
10554 ElementFound =
true;
10559 ElementFound =
true;
10588 else if(AVEntryPtr->
Command ==
"Fer")
10590 bool CorrectExit =
false;
10597 CorrectExit =
true;
10702 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10720 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10735 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10746 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10747 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10748 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10750 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10751 "," + AnsiString(Mass) +
"," + ModeStr);
10753 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10755 int RearExitPos = -1;
10757 for(
int x = 0; x < 4; x++)
10764 if(RearExitPos == -1)
10766 throw Exception(
"Error, RearExit == -1 in AddTrain");
10768 bool ReportFlag =
true;
10773 ReportFlag =
false;
10785 if(ModeStr ==
"Timetable")
10791 if(MaxRunningSpeed < 10)
10793 MaxRunningSpeed = 10;
10795 if(SignallerSpeed < 10)
10797 SignallerSpeed = 10;
10799 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10800 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10807 if(SignallerControl)
10844 if(!SignallerControl)
10859 if(!SignallerControl)
10870 AnsiString Loc =
"";
10887 if(!SignallerControl)
10906 int RouteNumber = -1;
10907 bool SignalsSet =
false;
10914 int RouteStartPosition;
10918 if(FirstPair.first == RouteNumber)
10920 RouteStartPosition = FirstPair.second;
10922 else if(SecondPair.first == RouteNumber)
10924 RouteStartPosition = SecondPair.second;
10928 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10934 else if(RouteNumber > -1)
10954 int LinkedRouteNumber = -1;
10975 int RouteStartPosition;
10979 if(FirstPair.first == RouteNumber)
10981 RouteStartPosition = FirstPair.second;
10983 else if(SecondPair.first == RouteNumber)
10985 RouteStartPosition = SecondPair.second;
10989 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10995 else if(RouteNumber > -1)
11015 int LinkedRouteNumber = -1;
11036 AnsiString(TrackVectorNumber));
11039 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11048 throw Exception(
"Error, VecPos not set in EntryPos");
11050 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
11055 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
11060 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
11074 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11082 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
11092 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
11113 return(RepeatTime);
11122 AnsiString RetStr =
"", PartStr =
"", MinMinsString;
11130 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
11138 if(Ptr->SignallerControl)
11140 RetStr =
"Train under signaller control";
11145 if(Ptr->ArrivalTime == Ptr->DepartureTime)
11147 if(Ptr->MinDwellTime > 30.1)
11149 double MDTdouble = Ptr->MinDwellTime / 60;
11150 double MDT = int(MDTdouble * 10);
11152 MinMinsString =
"mins";
11153 if((MDT < 1.1) && (MDT > 0.9))
11155 MinMinsString =
"min";
11166 if(Ptr->MinDwellTime > 30.1)
11168 double MDTdouble = Ptr->MinDwellTime / 60;
11169 double MDT = int(MDTdouble * 10);
11171 MinMinsString =
"mins";
11172 if((MDT < 1.1) && (MDT > 0.9))
11174 MinMinsString =
"min";
11187 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
11189 if(Ptr->MinDwellTime > 30.1)
11191 double MDTdouble = Ptr->MinDwellTime / 60;
11192 double MDT = int(MDTdouble * 10);
11194 MinMinsString =
"mins";
11195 if((MDT < 1.1) && (MDT > 0.9))
11197 MinMinsString =
"min";
11206 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
11210 else if(Ptr->FormatType ==
PassTime)
11214 else if(Ptr->Command ==
"Fns")
11220 else if(Ptr->Command ==
"F-nshs")
11223 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
11230 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11237 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11240 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
11243 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
11250 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
11252 PartStr =
"Terminate at " + Ptr->LocationName;
11254 else if(Ptr->Command ==
"Frh")
11256 PartStr =
"Terminate at " + Ptr->LocationName;
11258 else if(Ptr->Command ==
"Fer")
11260 AnsiString AllowedExits;
11264 else if(Ptr->Command ==
"Fjo")
11267 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11269 else if(Ptr->Command ==
"jbo")
11272 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
11274 else if(Ptr->Command ==
"fsp")
11279 else if(Ptr->Command ==
"rsp")
11284 else if(Ptr->Command ==
"cdt")
11288 else if(Ptr->Command ==
"dsc")
11292 else if(Ptr->Command ==
"cms")
11298 RetStr = RetStr +
'\n' + PartStr;
11306 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
11317 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
11320 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
11321 AnsiString DepTime =
"", EventTime =
"";
11322 bool CDTFlag =
false;
11324 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
11325 AnsiString TowardsLocation =
"";
11328 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
11330 TowardsLocation = AVI->LocationName;
11332 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
11341 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
11347 if(AVI->Command ==
"cdt")
11349 CDTFlag = !CDTFlag;
11352 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
11355 RetStr +=
"\nNew service splits at " + EventTime;
11359 if(AVI->Command ==
"jbo")
11362 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11366 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
11369 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
11373 if(AVI->Command ==
"Fjo")
11376 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
11380 if(AVI->Command ==
"Frh")
11382 RetStr +=
"\nNew service finishes and remains at location.";
11386 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
11391 if(TowardsLocation !=
"")
11393 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
11397 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
11402 if(TowardsLocation !=
"")
11404 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
11408 RetStr +=
"\nNew service departs at " + DepTime;
11577 ActiveTrackElementNameMapEntry.second = 0;
11583 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11586 if(TTBLFile.is_open())
11588 char *TrainTimetableString =
new char[10000];
11590 bool EndOfFile =
false;
11593 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11595 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11602 delete[] TrainTimetableString;
11606 AnsiString OneEntry(TrainTimetableString);
11607 bool FinalCallFalse =
false;
11608 while((Count == 0) && !
ProcessOneTimetableEntry(5, Count, OneEntry, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11612 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11613 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11618 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11620 delete[] TrainTimetableString;
11624 OneEntry = AnsiString(TrainTimetableString);
11630 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11632 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11642 OneEntry = AnsiString(TrainTimetableString);
11644 if(OneEntry.Length() > 9999)
11646 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11648 delete[] TrainTimetableString;
11652 bool FinalCallFalse =
false;
11653 if(!
ProcessOneTimetableEntry(6, Count, OneEntry, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11657 delete[] TrainTimetableString;
11661 if(EndOfFile && (Count < 2))
11664 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11666 delete[] TrainTimetableString;
11672 delete[] TrainTimetableString;
11677 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11688 bool CheckLocationsExistInRailway)
11818 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11828 if(OneEntry[1] !=
'*')
11830 int DelimPos = OneEntry.Pos(
';');
11831 int CPos = OneEntry.Pos(
',');
11832 if((CPos > 0) && (CPos < DelimPos))
11847 bool AllCommas =
true;
11849 for(
int x = 1; x < OneEntry.Length() + 1; x++)
11851 if(OneEntry[x] !=
',')
11856 if(AllCommas || (OneEntry ==
""))
11871 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11872 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11873 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11874 TDateTime StartTime(0);
11876 bool Warning =
false;
11903 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11904 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11905 double MaxBrakeRate = 0;
11906 double PowerAtRail = 0;
11907 int SignallerSpeed = 0;
11908 if(OneEntry[1] ==
'*')
11914 int Pos = OneEntry.Pos(
',');
11917 int SubStringLength = 20;
11918 if(OneEntry.Length() < 20)
11920 SubStringLength = OneEntry.Length();
11922 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneEntry.SubString(1, SubStringLength) +
"'....");
11926 TrainInfoStr = OneEntry.SubString(1, Pos - 1);
11927 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11938 TempTrainDataEntry.
HeadCode = HeadCode;
11942 if(Description !=
"")
11947 TempTrainDataEntry.
Mass = Mass;
11955 AnsiString NewRemainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11958 while(NewRemainder[NewRemainder.Length()] ==
',')
11960 if(NewRemainder.Length() > 1)
11962 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11971 if(NewRemainder ==
"")
11973 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneEntry +
"'");
11978 int CommaCount = 0;
11979 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11981 if(NewRemainder[x] ==
',')
11986 if(CommaCount == 0)
11988 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11990 int SubStringLength = 20;
11991 if(OneEntry.Length() < 20)
11993 SubStringLength = OneEntry.Length();
11996 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11997 OneEntry.SubString(1, SubStringLength) +
"'....");
12003 AnsiString OneLine =
"";
12008 bool FinishFlag =
false;
12010 for(
int x = 0; x < CommaCount + 1; x++)
12012 if((CommaCount == 0) || (x < CommaCount))
12017 if(CommaCount == 0)
12019 OneLine = NewRemainder;
12024 Pos = NewRemainder.Pos(
',');
12025 OneLine = NewRemainder.SubString(1, Pos - 1);
12026 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
12032 RearStartOrRepeatMins = 0;
12033 FrontStartOrRepeatDigits = 0;
12034 NumberOfRepeats = 0;
12035 if(!
SplitEntry(0, OneLine, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
12036 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
12038 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneLine +
"'");
12081 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneLine +
"'");
12085 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
12087 if(NewRemainder[1] !=
'R')
12090 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
12096 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12100 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
12103 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
12109 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
12114 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
12119 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
12122 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
12138 TDateTime TempTime;
12144 ActionVectorEntry.
Warning = Warning;
12167 ActionVectorEntry.
Command = Second;
12190 else if(FormatType ==
TimeCmd)
12196 ActionVectorEntry.
Command = Second;
12204 ActionVectorEntry.
Command = Second;
12205 ActionVectorEntry.
ExitList = ExitList;
12213 ActionVectorEntry.
Command = Second;
12227 ActionVectorEntry.
Command = Second;
12238 ActionVectorEntry.
Command = Second;
12248 ActionVectorEntry.
Command = Second;
12250 if((Second ==
"fsp") || (Second ==
"rsp"))
12265 ActionVectorEntry.
Command = Second;
12274 ActionVectorEntry.
Command = Second;
12280 ActionVectorEntry.
Command = Second;
12288 ActionVectorEntry.
Command = Second;
12297 ActionVectorEntry.
Command = Second;
12301 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12306 OneLine = NewRemainder;
12311 RearStartOrRepeatMins = 0;
12312 FrontStartOrRepeatDigits = 0;
12313 NumberOfRepeats = 0;
12314 if((FinishFlag) && (OneLine[1] !=
'R'))
12317 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneLine +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
12321 if(OneLine[1] !=
'R')
12323 if(!
SplitEntry(1, OneLine, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
12324 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
12326 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneLine +
"'.\nIf the program version is not the latest the "
12327 "timetable may have features that aren't compatible with the version in use.");
12343 if(Warning && (Second ==
"Frh"))
12345 TimetableMessage(GiveMessages,
"Error in line - '" + OneLine +
"': warnings cannot be given for 'Frh' events");
12349 if(Warning && (Second ==
"Fjo"))
12352 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
12359 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneLine +
"'");
12366 TDateTime TempTime;
12372 ActionVectorEntry.
Warning = Warning;
12379 ActionVectorEntry.
Command = Second;
12387 ActionVectorEntry.
Command = Second;
12396 ActionVectorEntry.
Command = Second;
12405 ActionVectorEntry.
Command = Second;
12415 ActionVectorEntry.
Command = Second;
12416 ActionVectorEntry.
ExitList = ExitList;
12420 ActionVectorEntry.
Command = Second;
12423 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12428 if(!
SplitRepeat(0, OneLine, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
12445 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12464 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
12469 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12484 if(TimeStr.Length() < 5)
12489 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12494 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12499 if(TimeStr[3] !=
':')
12504 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12509 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12514 while(TimeStr.Length() > 5)
12516 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12518 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12519 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12521 if((WholeHours + FracHour) >= 95.98334)
12526 Time = TDateTime((WholeHours + FracHour) / 24);
12534 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12543 TDateTime TempTime;
12545 if(OneLine.Length() > 0)
12547 if(OneLine[1] ==
'W')
12550 OneLine = OneLine.SubString(2, OneLine.Length() - 1);
12554 if(OneLine ==
"Frh")
12564 if(OneLine.Length() < 7)
12569 int Pos = OneLine.Pos(
';');
12577 First = OneLine.SubString(1, 5);
12583 AnsiString Remainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
12586 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
12589 if(Remainder.Length() < 7)
12594 Pos = Remainder.Pos(
';');
12601 Second = Remainder.SubString(1, 5);
12607 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12608 Pos = Third.Pos(
';');
12611 Fourth = Third.SubString(Pos + 1, Remainder.Length() - Pos);
12617 Third = Third.SubString(1, Pos - 1);
12618 for(
int x = 1; x <= Fourth.Length(); x++)
12620 if((Fourth[x] <
'0') || (Fourth[x] >
'9'))
12622 TimetableMessage(GiveMessages,
"Invalid character in minimum dwell time in " + OneLine +
". Must be a whole number of seconds.");
12627 if(Fourth.ToDouble() < 29.9)
12629 TimetableMessage(GiveMessages,
"Error in timetable - a minimum dwell time can't be less than 30 seconds: '" + OneLine +
"'");
12646 Pos = Remainder.Pos(
';');
12649 Second = Remainder;
12650 if(Second ==
"cdt")
12675 if((Pos != 0) && (
CheckLocationValidity(4, Remainder.SubString(1, Pos - 1),
false, CheckLocationsExistInRailway)))
12677 Second = Remainder.SubString(1, Pos - 1);
12680 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12686 for(
int x = 1; x <= Third.Length(); x++)
12688 if((Third[x] <
'0') || (Third[x] >
'9'))
12690 TimetableMessage(GiveMessages,
"Invalid character in minimum dwell time in " + OneLine +
". Must be a whole number of seconds.");
12695 if(Third.ToDouble() < 29.9)
12697 TimetableMessage(GiveMessages,
"Error in timetable - a minimum dwell time can't be less than 30 seconds: '" + OneLine +
"'");
12710 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12716 Second = Remainder.SubString(1, Pos - 1);
12718 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12720 Pos = Remainder.Pos(
';');
12727 Third = Remainder.SubString(1, Pos - 1);
12728 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12731 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12734 int SpacePos = Third.Pos(
' ');
12740 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12741 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12743 if(CheckLocationsExistInRailway)
12753 if(Second ==
"Snt")
12776 if(Second ==
"Sns-sh")
12795 if(Second ==
"F-nshs")
12809 if(Second ==
"Sns-fsh")
12823 if(Second ==
"Fns-sh")
12843 if(Second ==
"pas")
12858 if(Second ==
"Fer")
12865 if(CheckLocationsExistInRailway)
12876 if(Second ==
"dsc")
12878 if(Third.Length() > 60)
12880 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12884 for(
int x = 1; x < Third.Length() + 1; x++)
12887 if((Third[x] <
' ') && (Third[x] >= 0))
12889 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12901 if(Second ==
"cms")
12909 for(
int x = 1; x < Third.Length() + 1; x++)
12911 if((Third[x] <
'0') || (Third[x] >
'9'))
12913 TimetableMessage(GiveMessages,
"Train maximum speed must be a number in '" + Third +
"'");
12918 int MaxRunningSpeed = Third.ToInt();
12921 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be greater than 400km/h");
12925 if(MaxRunningSpeed < 10)
12928 TimetableMessage(GiveMessages,
"Train maximum running speed [" + Third +
"km/h] can't be less than 10km/h.");
12943 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12944 (Second !=
"Frh-sh"))
12956 if(Second ==
"Frh-sh")
12964 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12968 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12972 if((Second ==
"Sfs") || (Second ==
"Sns"))
12977 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12994 if((Text ==
"Snt") || (Text ==
"Sfs") || (Text ==
"Sns") || (Text ==
"Sns-fsh") || (Text ==
"Snt-sh") || (Text ==
"Sns-sh") ||
12995 (Text ==
"pas") || (Text ==
"jbo") || (Text ==
"fsp") || (Text ==
"rsp") || (Text ==
"cdt") || (Text ==
"dsc") ||
12996 (Text ==
"cms") || (Text ==
"Fns") || (Text ==
"Fjo") || (Text ==
"Fer") || (Text ==
"Frh-sh") || (Text ==
"Fns-sh") ||
12997 (Text ==
"F-nshs") || (Text ==
"Frh"))
13011 bool ErrorFlag =
false;
13013 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
13017 int pos = SplitDistributionString.Pos(
'-');
13024 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
13025 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
13028 int x = MassStr.ToInt();
13029 int y = PowerStr.ToInt();
13030 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
13035 catch(
const Exception &e)
13042 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
13043 "power for the new split-off train");
13064 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
13069 for(
int x = 1; x < LocStr.Length() + 1; x++)
13071 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
13085 if(CheckLocationsExistInRailway)
13090 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
13091 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
13092 "that includes a continuation will not be valid.");
13110 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
13113 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
13118 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
13120 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
13122 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
13128 for(
int x = 3; x >= 0; x--)
13130 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
13131 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
13133 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
13149 AnsiString CurrentID =
"";
13151 if(IDSet.Length() == 0)
13153 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
13157 for(
int x = 1; x <= IDSet.Length(); x++)
13160 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
13162 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
13184 int Pos = IDSet.Pos(
' ');
13195 CurrentID = IDSet.SubString(1, Pos - 1);
13196 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
13208 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
13215 if(!ExitList.empty())
13217 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
13219 if(*ELIT == VecPos)
13221 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
13228 ExitList.push_back(VecPos);
13238 Pos = IDSet.Pos(
' ');
13245 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
13252 AnsiString Remainder =
"";
13253 int SemiColonCount = 0;
13255 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
13257 if(TrainInfoStr[x] ==
';')
13262 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
13264 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
13265 "'. Should be headcode + optional description for a continuing service;" +
13266 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
13270 if(SemiColonCount == 0)
13272 HeadCode = TrainInfoStr;
13281 if(SemiColonCount == 1)
13283 Pos = TrainInfoStr.Pos(
';');
13284 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
13285 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
13291 if(Description ==
"")
13293 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
13297 if(Description.Length() > 60)
13299 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
13303 for(
int x = 1; x < Description.Length() + 1; x++)
13306 if((Description[x] <
' ') && (Description[x] >= 0))
13308 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
13317 Pos = TrainInfoStr.Pos(
';');
13318 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
13319 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
13325 Pos = Remainder.Pos(
';');
13326 Description = Remainder.SubString(1, Pos - 1);
13327 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13328 if(Description ==
"")
13330 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
13334 if(Description.Length() > 60)
13336 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
13340 for(
int x = 1; x < Description.Length() + 1; x++)
13343 if((Description[x] <
' ') && (Description[x] >= 0))
13345 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
13350 Pos = Remainder.Pos(
';');
13351 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
13353 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13354 if(StartSpeedStr ==
"")
13356 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
13360 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
13362 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
13364 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
13369 StartSpeed = StartSpeedStr.ToInt();
13375 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13379 Pos = Remainder.Pos(
';');
13380 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
13382 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13383 if(MaxRunningSpeedStr ==
"")
13385 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
13389 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
13391 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
13393 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
13398 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
13401 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be greater than 400km/h");
13405 if(MaxRunningSpeed < 10)
13408 TimetableMessage(GiveMessages,
"Train maximum running speed [" + MaxRunningSpeedStr +
"km/h] can't be less than 10km/h.");
13412 Pos = Remainder.Pos(
';');
13413 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
13415 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13418 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
13422 for(
int x = 1; x < MassStr.Length() + 1; x++)
13424 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
13426 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
13431 Mass = MassStr.ToInt() * 1000;
13437 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
13443 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
13447 Pos = Remainder.Pos(
';');
13448 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
13450 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13451 if(MaxBrakeForceStr ==
"")
13453 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
13457 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
13459 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
13461 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
13466 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
13469 if((MaxBrakeForce / Mass) > 1)
13471 MaxBrakeForce = Mass;
13474 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
13478 if((MaxBrakeForce / Mass) < 0.01)
13480 MaxBrakeForce = Mass * 0.01;
13483 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
13488 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
13490 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
13492 if(SemiColonCount == 6)
13494 GrossPowerStr = Remainder;
13495 SignallerSpeedStr =
"30";
13499 Pos = Remainder.Pos(
';');
13500 GrossPowerStr = Remainder.SubString(1, Pos - 1);
13501 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13504 if(GrossPowerStr ==
"")
13506 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
13510 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
13512 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
13514 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
13520 double GrossPower = GrossPowerStr.ToInt() * 1000;
13527 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
13531 else if(GrossPower == 0)
13536 else if((GrossPower > 0) && (GrossPower < 10000))
13539 GrossPower = 10000;
13541 PowerAtRail = GrossPower * 0.8;
13545 if(SignallerSpeedStr ==
"")
13547 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
13551 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
13553 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
13555 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
13560 SignallerSpeed = SignallerSpeedStr.ToInt();
13566 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13570 if(SignallerSpeed < 10)
13573 SignallerSpeed = 10;
13576 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
13594 if(OneEntry.Length() < 7)
13596 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13600 int SemiColonCount = 0;
13602 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13604 if(OneEntry[x] ==
';')
13609 if(SemiColonCount != 3)
13611 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13615 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13617 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13621 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13626 Pos = Remainder.Pos(
';');
13627 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13629 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13630 if(MinutesStr ==
"")
13632 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13636 if(MinutesStr.Length() > 3)
13639 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13643 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13645 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13647 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13652 RearStartOrRepeatMins = MinutesStr.ToInt();
13653 if(RearStartOrRepeatMins == 0)
13655 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13659 Pos = Remainder.Pos(
';');
13660 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13662 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13663 if(DigitsStr ==
"")
13665 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13669 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13671 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13673 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13678 if(DigitsStr.Length() > 2)
13680 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13684 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13698 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13702 AnsiString NumberStr = Remainder;
13704 if(NumberStr ==
"")
13706 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13710 if(NumberStr.Length() > 4)
13713 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13717 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13719 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13722 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13727 NumberOfRepeats = NumberStr.ToInt();
13728 if(NumberOfRepeats == 0)
13730 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
14003 TDateTime LastArrivalTime;
14004 double MinDwellTime;
14007 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
14028 TwoLocationFlag =
false;
14034 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
14048 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
14064 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
14076 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
14102 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh are not permitted immediately after an Snt entry for: " +
14115 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
14116 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
14117 "location of any other type of finish.");
14123 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
14129 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
14130 "event for: " + TDEntry.
HeadCode);
14140 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14145 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
14155 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14160 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
14170 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14181 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
14191 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
14203 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14210 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
14219 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
14238 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
14240 AnsiString LocationName =
"";
14254 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' event (stationary train) followed by event '"
14255 + AVEntry1.
OneLineText +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14264 if(AVEntry0.
Command ==
"Snt-sh")
14278 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Snt' command for a moving train is not followed by 'Fer', 'pas' or an arrival for: " +
14294 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' (stationary train) followed by event '"
14295 + AVEntry1.
OneLineText +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14306 bool FoundFlag =
false;
14310 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
14312 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14324 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
14337 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14362 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14384 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14406 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14431 bool LocFoundFlag, FnsFoundFlag;
14435 LocFoundFlag =
false;
14436 FnsFoundFlag =
false;
14437 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
14442 FnsFoundFlag =
true;
14451 LocFoundFlag =
true;
14462 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14463 "by an event at the same location that has an identified location name, normally an arrival, see "
14470 if(FnsFoundFlag && !LocFoundFlag)
14472 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
14473 "by an event at the same location that has an identified location name, normally an arrival, see "
14487 if(AVEntry0.
Command ==
"Sns")
14499 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient events follwing an 'Sns' event for: " + TDEntry.
HeadCode);
14507 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event (stationary train) is followed by event '" + AVEntry1.
OneLineText
14508 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14516 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event (stationary train) is followed by event '" + AVEntry1.
OneLineText +
"' (moving train) for: "
14517 + TDEntry.
HeadCode +
". At least one is incorrect.");
14524 TDateTime SnsEventTime = AVEntry0.
EventTime;
14527 bool BreakFlag =
false;
14530 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14535 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
14557 if(AVEntry0.
Command ==
"Sfs")
14559 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14567 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
14579 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14584 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14604 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14611 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see "
14627 if(AVEntry0.
Command ==
"Sfs")
14639 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
14647 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event (stationary train) is followed by event '" + AVEntry1.
OneLineText +
14648 "' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14656 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by illegal event '" + AVEntry1.
OneLineText +
"' for: "
14664 TDateTime SfsEventTime = AVEntry0.
EventTime;
14666 bool BreakFlag =
false;
14669 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
14674 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
14694 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14699 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14720 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14727 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14732 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
14735 "Please make sure that the finish event of the service that links to this event is preceded by an "
14736 "event at the same location that has an identified location name, normally an arrival.");
14741 else if(AVEntry.
Command ==
"Snt-sh")
14744 "Please make sure that the service starts with zero speed and is at a named location.");
14749 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
14752 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
14759 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14771 bool DwellTimeWarningGiven =
false;
14773 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14783 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
14790 if(AVEntry.
Command ==
"F-nshs")
14795 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14824 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14834 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: "
14843 SecondPassMessage(GiveMessages,
"Error in timetable - a train split event (stationary trains) is followed by event '" + AVEntry2.
OneLineText
14844 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14863 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14882 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14901 +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14911 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14920 "' (moving train) is followed by event '" + AVEntry2.
OneLineText +
"' (stationary train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
14925 if(!DwellTimeWarningGiven)
14929 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
14930 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
14931 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
14932 DwellTimeWarningGiven =
true;
14936 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
14937 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
14938 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
14939 DwellTimeWarningGiven =
true;
14955 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time (moving train) is followed by event '" + AVEntry2.
OneLineText +
"' (stationary train) for: "
14956 + TDEntry.
HeadCode +
". At least one is incorrect.");
14978 bool DwellTimeWarningGiven =
false;
14979 bool LastEntryIsAnArrival =
false;
14980 LastArrivalTime = TDateTime(-1);
14981 DwellTimeWarningGiven =
false;
14988 LastEntryIsAnArrival =
false;
14989 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14996 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14998 if(LastEntryIsAnArrival)
15002 LastEntryIsAnArrival =
false;
15003 if((LastArrivalTime > TDateTime(0)) && !DwellTimeWarningGiven)
15005 if(((
double(AVEntry.
DepartureTime - LastArrivalTime)) > (0.1 / 86400)) && ((AVEntry.
DepartureTime - LastArrivalTime) < TDateTime((MinDwellTime - 0.05) / 86400)))
15007 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
15008 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
15009 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
15010 DwellTimeWarningGiven =
true;
15012 if(((
double(AVEntry.
DepartureTime - LastArrivalTime)) < (0.1 / 86400)) && (MinDwellTime > 30.05))
15014 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
15015 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
15016 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
15017 DwellTimeWarningGiven =
true;
15022 SecondPassMessage(GiveMessages,
"Error in timetable - a minimum dwell time is not permitted for a departure, "
15023 "add it to the corresponding arrival instead, see: " + TDEntry.
HeadCode);
15035 LastEntryIsAnArrival =
true;
15042 LastEntryIsAnArrival =
true;
15043 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15045 LastArrivalTime = TDateTime(-1);
15046 DwellTimeWarningGiven =
false;
15052 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
15054 if(LastEntryIsAnArrival)
15058 LastEntryIsAnArrival =
false;
15059 if((LastArrivalTime > TDateTime(0)) && !DwellTimeWarningGiven)
15061 if(((
double(AVEntry.
DepartureTime - LastArrivalTime)) > (0.1 / 86400)) && ((AVEntry.
DepartureTime - LastArrivalTime) < TDateTime((MinDwellTime - 0.05) / 86400)))
15063 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
15064 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
15065 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
15066 DwellTimeWarningGiven =
true;
15068 if(((
double(AVEntry.
DepartureTime - LastArrivalTime)) < (0.1 / 86400)) && (MinDwellTime > 30.05))
15070 SecondPassMessage(GiveMessages,
"Warning: Service " + TDEntry.
HeadCode +
" has a minimum dwell time that is greater than the timetabled stop duration for '" + AVEntry.
OneLineText +
15071 "'. This is not an error but it will cause the train to run late and the 'Actions Due' panel to give inaccurate times.\n\n"
15072 "Note that this warning can't be given in every circumstance where a minimum dwell time is set too high so please try to avoid it.");
15073 DwellTimeWarningGiven =
true;
15078 SecondPassMessage(GiveMessages,
"Error in timetable - a minimum dwell time is not permitted for a departure, "
15079 "add it to the corresponding arrival instead, see: " + TDEntry.
HeadCode);
15091 LastEntryIsAnArrival =
true;
15101 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15109 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
15117 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival (stationary train) is followed by event '"
15118 + AVEntry2.
OneLineText +
"' (moving train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
15129 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
15138 +
"' (stationary train) for: " + TDEntry.
HeadCode +
". At least one is incorrect.");
15152 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15159 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
15163 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
15170 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
15174 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
15183 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
15187 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
15194 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
15205 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15221 +
"' has a later arrival than departure time for: " + TDEntry.
HeadCode);
15229 +
"' has too early an arrival time for: " + TDEntry.
HeadCode);
15244 +
"' has a time that is too early for: " + TDEntry.
HeadCode);
15257 +
"' has a time that is too early for: " + TDEntry.
HeadCode);
15270 +
"' has a time that is set too early for: " + TDEntry.
HeadCode +
".");
15281 AnsiString LastLocationName =
"";
15285 bool LastEntryIsAnArrival =
false;
15290 LastEntryIsAnArrival =
false;
15291 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
15292 if(LastLocationName !=
"")
15294 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
15296 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
15310 +
"' is at a location that differs from the earlier event for: " + TDEntry.
HeadCode);
15322 +
"' is at a location that differs from the earlier event for: " + TDEntry.
HeadCode);
15334 TwoLocationFlag =
true;
15339 LastEntryIsAnArrival =
false;
15343 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
15346 +
"' is at a location that differs from the arrival location for: " + TDEntry.
HeadCode);
15351 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
15354 +
"' is at the same location as the earlier departure event for: " + TDEntry.
HeadCode);
15360 LastEntryIsAnArrival = !LastEntryIsAnArrival;
15366 LastEntryIsAnArrival =
true;
15367 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
15368 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15381 +
"' is at a location that differs from the earlier event for: " + TDEntry.
HeadCode);
15393 +
"' is at a location that differs from the earlier event for: " + TDEntry.
HeadCode);
15405 TwoLocationFlag =
true;
15410 LastEntryIsAnArrival =
false;
15414 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
15417 +
"' is at a location that differs from the earlier arrival event for: " + TDEntry.
HeadCode);
15425 +
"' is at the same location as the earlier departure event for: " + TDEntry.
HeadCode +
". This may be an error.");
15432 LastEntryIsAnArrival = !LastEntryIsAnArrival;
15440 AnsiString LocationNameToBeChecked =
"";
15445 unsigned int y = 0;
15459 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
15460 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
15478 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
15487 TwoLocationFlag =
true;
15498 if(TwoLocationFlag)
15508 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15513 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
15515 AnsiString LocName =
"";
15521 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
15528 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
15551 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15576 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15598 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15620 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15639 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15642 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
15657 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15662 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
15666 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
15670 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
15674 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
15713 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15715 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
15721 SecondPassMessage(GiveMessages,
"Error in timetable - a continuation name (" + LocName +
") must not be included in the timetable, see service " + HC);
15734 int IncMinutes = 0;
15744 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15750 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
15756 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
15761 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15767 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
15772 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15785 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15819 if(HeadCode.Length() > 4)
15821 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15832 int ForwardCount = 0;
15833 int ReverseCount = 0;
15835 if(MainHeadCode == SecondHeadCode)
15837 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15846 if(TDEntry.
HeadCode == MainHeadCode)
15848 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15863 if(ForwardCount == 0)
15866 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15868 if(ForwardCount > 2)
15871 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15872 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15881 if(TDEntry.
HeadCode == SecondHeadCode)
15883 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15898 if(ReverseCount == 0)
15900 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15905 if(ReverseCount > 2)
15908 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15909 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15914 if(ForwardCount != ReverseCount)
15916 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15917 " than the other way round");
15948 int ForwardCount = 0;
15949 int ReverseCount = 0;
15950 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15959 if(TDEntry.
HeadCode == MainHeadCode)
15961 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15964 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15969 ForwardEntryPtr = &AVEntry;
15971 ForwardTDVectorNumber = x;
15974 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15975 (AVEntry.
Command ==
"Frh-sh")))
15980 ForwardEntryPtr = &AVEntry;
15982 ForwardTDVectorNumber = x;
15988 if(ForwardCount == 0)
15991 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15993 if(ForwardCount > 1)
15995 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
16005 if(TDEntry.
HeadCode == OtherHeadCode)
16007 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16010 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
16016 ReverseEntryPtr = &AVEntry;
16017 ReverseTDVectorNumber = x;
16020 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
16026 ReverseEntryPtr = &AVEntry;
16027 ReverseTDVectorNumber = x;
16034 if(ReverseCount == 0)
16036 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
16041 if(ReverseCount > 1)
16043 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16050 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
16051 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
16052 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
16053 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
16057 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
16064 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
16069 if(SetDataAndCheckLocations)
16071 if(ForwardEntryPtr->LocationName ==
"")
16073 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
16074 ". One or other service does not have a location set");
16081 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
16082 ". One or other service does not have a location set");
16087 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16089 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
16090 " is at a different location to the referencing train " + MainHeadCode);
16099 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16101 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
16102 " has a different event time to the referencing train " + MainHeadCode);
16110 if(ForwardShuttleStart && ReverseShuttleFinish)
16115 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
16116 " first repeat restart time not consistent with finish service " + OtherHeadCode);
16122 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
16125 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16127 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
16128 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16134 if(ReverseEntryPtr->
Command ==
"Fjo")
16137 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16139 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
16140 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16146 if(ReverseEntryPtr->
Command ==
"Fns")
16149 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16151 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
16152 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
16158 if(ForwardEntryPtr->Command ==
"Sfs")
16160 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
16163 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
16170 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
16172 if(ReverseEntryPtr->
Command !=
"Sfs")
16174 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
16182 if(SetDataAndCheckLocations)
16186 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
16193 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
16199 bool StationLocation =
false;
16202 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
16206 StationLocation =
true;
16210 if(StationLocation)
16214 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
16224 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
16230 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16242 if(ForwardEntryPtr->Command ==
"Sns")
16244 if(ReverseEntryPtr->
Command !=
"Fns")
16246 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
16247 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
16253 if(ForwardEntryPtr->Command ==
"Fns")
16255 if(ReverseEntryPtr->
Command !=
"Sns")
16257 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
16258 " and forms a new service with headcode " + OtherHeadCode);
16265 if(SetDataAndCheckLocations)
16267 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16279 if(ForwardEntryPtr->Command ==
"jbo")
16281 if(ReverseEntryPtr->
Command !=
"Fjo")
16283 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
16284 " and is joined by a train with headcode " + OtherHeadCode);
16290 if(ForwardEntryPtr->Command ==
"Fjo")
16292 if(ReverseEntryPtr->
Command !=
"jbo")
16294 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
16295 " and joins a train with headcode " + OtherHeadCode);
16302 if(SetDataAndCheckLocations)
16304 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16320 if(ForwardShuttleStart)
16323 if(!ReverseShuttleFinish)
16326 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
16327 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
16333 if(ReverseShuttleStart)
16336 if(!ForwardShuttleFinish)
16339 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
16340 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
16347 if(SetDataAndCheckLocations)
16349 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16362 bool MainRepeat =
false, OtherRepeat =
false;
16372 OtherRepeat =
true;
16375 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
16377 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
16378 " and the associated train with headcode " + OtherHeadCode);
16383 if(MainRepeat && OtherRepeat)
16389 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
16390 " and the associated train with headcode " + OtherHeadCode);
16412 while(Input[1] ==
' ')
16414 if(Input.Length() > 1)
16416 Input = Input.SubString(2, Input.Length() - 1);
16430 while(Input[Input.Length()] ==
' ')
16432 if(Input.Length() > 1)
16434 Input = Input.SubString(1, Input.Length() - 1);
16444 AnsiString Output =
"";
16445 bool DelimiterFound =
false;
16447 for(
int x = 1; x < Input.Length() + 1; x++)
16451 if(Input[x] ==
' ')
16456 if((Input[x] !=
',') && (Input[x] !=
';'))
16458 DelimiterFound =
false;
16459 Output = Output + Input[x];
16463 DelimiterFound =
true;
16464 Output = Output + Input[x];
16476 DelimiterFound =
false;
16477 for(
int x = Input.Length(); x > 0; x--)
16481 if(Input[x] ==
' ')
16486 if((Input[x] !=
',') && (Input[x] !=
';'))
16488 DelimiterFound =
false;
16489 Output = AnsiString(Input[x]) + Output;
16493 DelimiterFound =
true;
16494 Output = AnsiString(Input[x]) + Output;
16519 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
16521 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
16533 LocationName = LocRear;
16537 LocationName = LocFront;
16539 if(LocationName ==
"")
16560 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
16601 int RearPosition = 0, FrontPosition = 0;
16604 if(RearPosition < 0)
16611 if(FrontPosition < 0)
16623 for(
int x = 0; x < 4; x++)
16625 if(RearTrackElement.
Conn[x] == FrontPosition)
16640 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
16647 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
16653 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
16684 AnsiString(RearExitPos));
16695 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
16697 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
16700 AnsiString RearName, FrontName;
16716 FrontName = FrontTrackElement.
ElementID;
16719 int LockedVectorNumber;
16839 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
16844 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
16852 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
16857 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
16891 "," + AnsiString(IncDigits));
16894 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16899 return(BaseHeadCode);
16901 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16902 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16904 while(NextRepeatDigits >= 100)
16906 NextRepeatDigits -= 100;
16908 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16910 if(NextRepeatDigitsStr.Length() < 2)
16912 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16914 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16917 return(NextRepeatHeadCode);
16925 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16926 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16928 return(NextRepeatTime);
16937 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16938 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16939 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16940 int RepeatSecs = RepeatMinutes * 60;
16942 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16976 NonRepeatingHeadCode);
16977 int ForwardCount = 0;
16978 int ReverseCount = 0;
16979 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16989 if(TDEntry.
HeadCode == MainHeadCode)
16991 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16997 ForwardEntryPtr = &AVEntry;
16999 ForwardTDVectorNumber = x;
17004 if(ForwardCount == 0)
17007 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
17009 if(ForwardCount > 1)
17011 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
17021 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
17023 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
17030 ReverseEntryPtr = &AVEntry;
17031 ReverseTDVectorNumber = x;
17037 if(ReverseCount == 0)
17039 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
17044 if(ReverseCount > 1)
17046 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
17047 NonRepeatingHeadCode);
17052 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
17054 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
17059 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
17061 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
17066 if(SetDataAndCheckLocations)
17068 if(ForwardEntryPtr->LocationName ==
"")
17070 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
17071 ". One or other service does not have a location set");
17078 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
17079 ". One or other service does not have a location set");
17084 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
17086 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
17087 " is at a different location to the referencing train " + MainHeadCode);
17093 if(ForwardEntryPtr->Command ==
"F-nshs")
17096 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
17098 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
17099 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
17105 if(ForwardEntryPtr->Command ==
"Fns-sh")
17109 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
17111 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
17112 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
17118 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
17121 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
17123 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
17124 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
17142 if(ForwardEntryPtr->Command ==
"Sns-sh")
17144 if(ReverseEntryPtr->
Command !=
"F-nshs")
17146 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
17147 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
17153 if(ForwardEntryPtr->Command ==
"F-nshs")
17155 if(ReverseEntryPtr->
Command !=
"Sns-sh")
17157 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
17158 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
17165 if(SetDataAndCheckLocations)
17167 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
17179 if(ForwardEntryPtr->Command ==
"Sns-fsh")
17181 if(ReverseEntryPtr->
Command !=
"Fns-sh")
17184 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
17185 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
17191 if(ForwardEntryPtr->Command ==
"Fns-sh")
17193 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
17196 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
17197 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
17204 if(SetDataAndCheckLocations)
17206 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
17230 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
17231 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
17232 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
17233 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
17235 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
17259 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
17262 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
17263 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
17265 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
17267 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
17272 while(LastActionCommand ==
"Fns")
17274 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
17275 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
17276 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
17279 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
17280 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
17287 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
17290 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
17291 ". The linking of two or more shuttles is not permitted.");
17311 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
17329 ShowMessage(Message);
17338 int Mins = Input, Hrs = 0;
17344 AnsiString AnsiMins = AnsiString(Mins);
17345 if(AnsiMins.Length() == 1)
17347 AnsiMins =
"0" + AnsiMins;
17349 AnsiString AnsiHrs = AnsiString(Hrs);
17350 if(AnsiHrs.Length() == 1)
17352 AnsiHrs =
"0" + AnsiHrs;
17355 return(AnsiHrs +
':' + AnsiMins);
17399 AnsiString(ActionEventType) +
"," + LocationID);
17400 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
17405 Prefix =
" ERROR: ";
17408 Prefix =
" HELD: ";
17409 ErrorLog =
" can't enter railway, train obstructing entry position ";
17410 WarningStr =
" can't enter railway, train obstructing entry position ";
17415 Prefix =
" HELD: ";
17416 ErrorLog =
" can't enter railway, route set against it at entry position ";
17417 WarningStr =
" can't enter railway, route set against it at entry position ";
17422 Prefix =
" HELD: ";
17423 ErrorLog =
" can't be created, train obstructing at ";
17424 WarningStr =
" can't be created, train obstructing at ";
17429 Prefix =
" HELD: ";
17430 ErrorLog =
" can't be created on a locked route at ";
17431 WarningStr =
" can't be created on a locked route at ";
17436 Prefix =
" HELD: ";
17437 ErrorLog =
" can't enter on a locked route at ";
17438 WarningStr =
" can't enter on a locked route at ";
17443 Prefix =
" HELD: ";
17444 ErrorLog =
" can't be created, points set wrongly at ";
17445 WarningStr =
" can't be created, points set wrongly at ";
17450 ErrorLog =
" left railway unexpectedly at ";
17455 ErrorLog =
" left railway at an incorrect exit at ";
17460 ErrorLog =
" failed to split - location too short at ";
17461 WarningStr =
" failed to split, location too short at ";
17466 Prefix =
" HELD: ";
17467 ErrorLog =
" unable to split - other train obstructing at ";
17468 WarningStr =
" unable to split - other train obstructing at ";
17473 ErrorLog =
" stopped at buffers unexpectedly at position ";
17477 ErrorLog =
" failed to stop at ";
17482 ErrorLog =
" failed to split at ";
17487 ErrorLog =
" failed to be joined by other train at ";
17492 ErrorLog =
" failed to change its description at ";
17497 ErrorLog =
" failed to change its maximum speed at ";
17502 ErrorLog =
" failed to join other train at ";
17507 ErrorLog =
" failed to terminate at ";
17512 ErrorLog =
" failed to form new service at ";
17517 ErrorLog =
" failed to exit railway ";
17522 ErrorLog =
" failed to change direction at ";
17527 ErrorLog =
" failed to pass ";
17532 ErrorLog =
" facing buffers and unable to start at ";
17536 ErrorLog =
" DERAILED at position ";
17537 Prefix =
" DERAILMENT: ";
17542 ErrorLog =
" CRASHED INTO BUFFERS at ";
17543 Prefix =
" CRASH: ";
17548 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
17549 Prefix =
" CRASH: ";
17554 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
17555 Prefix =
" CRASH: ";
17559 else if(ActionEventType ==
FailSPAD)
17561 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
17562 Prefix =
" SPAD: ";
17567 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
17568 Prefix =
" SPAD RISK: ";
17573 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
17577 Prefix =
" WARNING: ";
17578 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
17579 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
17584 Prefix =
" WARNING: ";
17585 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
17586 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
17591 Prefix =
" WARNING: ";
17592 ErrorLog =
" is without power so it can't depart from ";
17593 WarningStr =
" is without power so it can't depart from ";
17598 Prefix =
" WARNING: ";
17599 ErrorLog =
" can't depart because there is a train in front at ";
17600 WarningStr =
" can't depart because there is a train in front at ";
17638 std::ofstream OutFile(
"TrainData.csv");
17642 ShowMessage(
"Output file TrainData.csv failed to open");
17649 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
17654 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
17655 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
17656 "RepeatNumber" <<
'\n' <<
'\n';
17657 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
17660 AnsiString TimetableEntryTypeStr;
17666 TimetableEntryTypeStr =
"NoFormat";
17672 TimetableEntryTypeStr =
"TimeLoc";
17678 TimetableEntryTypeStr =
"TimeTimeLoc";
17684 TimetableEntryTypeStr =
"TimeCmd";
17690 TimetableEntryTypeStr =
"StartNew";
17696 TimetableEntryTypeStr =
"TimeCmdHeadCode";
17702 TimetableEntryTypeStr =
"FinRemHere";
17708 TimetableEntryTypeStr =
"FNSShuttle";
17714 TimetableEntryTypeStr =
"SNTShuttle";
17720 TimetableEntryTypeStr =
"SNSShuttle";
17726 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
17732 TimetableEntryTypeStr =
"FSHNewService";
17738 TimetableEntryTypeStr =
"Repeat";
17744 TimetableEntryTypeStr =
"Default";
17755 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
17756 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
17759 AnsiString RunningEntryStr;
17765 RunningEntryStr =
"NotStarted";
17771 RunningEntryStr =
"Running";
17777 RunningEntryStr =
"Exited";
17781 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
17798 ShowMessage(Message);
17799 BaseTime = TDateTime::CurrentDateTime();
17813 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17826 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17828 for(
int x = 0; x < NumberOfTrains; x++)
17830 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17850 int NumberOfTrains;
17857 for(
int x = 0; x < NumberOfTrains; x++)
17894 for(
int x = 0; x < LockedRouteVectorSize; x++)
17901 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17912 int LockedRouteVectorSize;
17919 for(
int x = 0; x < LockedRouteVectorSize; x++)
17977 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17985 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17996 int ContinuationAutoSigVectorSize;
18003 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
18073 if(AVFirstEntry.
Command ==
"Snt")
18097 CTEMMP.second = CTEEntry;
18104 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
18112 CTEMMP.second = CTEEntry;
18133 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
18150 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
18152 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
18163 AnsiString RetStr =
"", PartStr =
"";
18278 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18282 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18284 AnsiString ShortTTName =
"";
18286 for(
int x = TTFileName.Length(); x > 0; x--)
18288 if(TTFileName[x] ==
'\\')
18290 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
18295 ShowMessage(
"Creates two timetables named " + ShortTTName +
18296 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
18298 Screen->Cursor = TCursor(-11);
18300 AnsiString FormatNoDPStr =
"#######0";
18301 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
18304 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
18311 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
18313 if(TrainDataEntry.
Mass > 0)
18315 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
18319 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
18323 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
18327 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
18329 FirstHeadCode = TrainDataEntry.
HeadCode;
18330 int IncDigits = 0, IncMinutes = 0;
18332 if(!ActionVector.empty())
18334 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18336 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
18337 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18355 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18360 AnsiString PartStr =
"", TimeStr =
"";
18377 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
18381 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
18391 PartStr =
"Enters at " + LocName;
18404 PartStr =
"Created at " + LocName;
18418 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
18423 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18429 else if(ActionVectorEntry.
Command ==
"Sfs")
18431 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
18435 else if(ActionVectorEntry.
Command ==
"Sns")
18437 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18445 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18451 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
18459 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
18462 AnsiString FirstHeadCode = TDE->
HeadCode;
18466 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
18478 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18480 OneTTEntry.
Action = PartStr;
18481 OneTTEntry.
Time = TimeStr;
18483 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18488 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
18494 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
18499 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
18507 else if(ActionVectorEntry.
Command ==
"jbo")
18509 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
18513 else if(ActionVectorEntry.
Command ==
"fsp")
18517 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18521 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18526 else if(ActionVectorEntry.
Command ==
"rsp")
18530 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
18534 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
18539 else if(ActionVectorEntry.
Command ==
"cdt")
18541 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
18544 else if(ActionVectorEntry.
Command ==
"dsc")
18546 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
18549 else if(ActionVectorEntry.
Command ==
"cms")
18551 PartStr =
"Change maximum speed to " + ActionVectorEntry.
NewMaxSpeed +
" at " + ActionVectorEntry.
LocationName;
18557 if(ActionVectorEntry.
Command ==
"Fns")
18559 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18563 else if(ActionVectorEntry.
Command ==
"F-nshs")
18565 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18571 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
18578 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18584 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
18591 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
18596 else if(ActionVectorEntry.
Command ==
"Frh")
18598 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
18603 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18607 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18617 else if(ActionVectorEntry.
Command ==
"Fer")
18619 AnsiString AllowedExits;
18623 else if(ActionVectorEntry.
Command ==
"Fjo")
18625 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
18634 OneTTEntry.
Action = PartStr;
18635 OneTTEntry.
Time = TimeStr;
18642 AllTTTrains->push_back(OneTTLine);
18646 std::ofstream TTFile(TTFileName.c_str());
18650 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
18651 delete AllTTTrains;
18686 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
18687 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18689 TTFile << AllTTTrains->at(x).Header.c_str();
18692 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18694 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18696 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
18700 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
18703 TTFile <<
'\n' <<
'\n';
18705 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
18707 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
18708 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18710 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
18712 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
18716 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
18721 TTFile <<
'\n' <<
'\n';
18726 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18728 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
18730 std::ofstream TTFile2(TTFileName2.c_str());
18734 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
18735 delete AllTTTrains;
18739 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
18740 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
18741 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
18743 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
18748 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
18749 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
18751 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
18753 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
18755 bool GiveMessagesFalse =
false;
18756 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
18757 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
18758 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
18763 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
18764 TimeString = TimeString.SubString(9, 5);
18765 ActionString +=
" " + OtherHeadCode;
18767 if(TimeString.SubString(1, 7) ==
"End at ")
18770 TimeString = TimeString.SubString(8, 5);
18772 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
18773 AnsiMultiMapEntry.first = TimeString;
18774 AnsiMultiMapEntry.second = OneLine;
18775 TAMM->insert(AnsiMultiMapEntry);
18780 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
18782 TTFile2 << (AMMIT->second).c_str();
18784 delete AllTTTrains;
18793 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
18797 bool AnalysisError =
false;
18798 AnsiString SequenceLog =
"SequenceLog\n";
18841 TTrainDataVector::iterator TDVIt, TDVCopyIt;
18843 int IteratorNumber = 0;
18844 AnsiString AnsiSuffix =
"";
18851 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
18854 AnsiSuffix = AnsiString(Suffix);
18855 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
18856 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
18862 int Increment = 0, SlashPos;
18864 AnsiString LinkedHeadCode;
18868 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
18870 if(AVEIt->LinkedTrainEntryPtr != NULL)
18879 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18881 if(LinkedHeadCode[x] ==
'/')
18883 SlashPos = LinkedHeadCode.Length() - x + 1;
18886 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18887 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18888 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18894 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18898 AVEIt->OtherHeadCode =
"";
18900 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18902 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18906 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18909 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18911 if(LinkedHeadCode[x] ==
'/')
18913 SlashPos = LinkedHeadCode.Length() - x + 1;
18916 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18917 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18918 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18924 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18928 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18933 SequenceLog +=
"1\n";
18936 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18942 ServiceCallingLocsList.clear();
18943 if(ActionVector.empty())
18947 if(ActionVector.at(0).SignallerControl)
18951 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18969 int HLoc = TE.
HLoc;
18970 int VLoc = TE.
VLoc;
18971 AnsiString HString;
18972 AnsiString VString;
18975 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18979 HString = AnsiString(HLoc);
18983 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18987 VString = AnsiString(VLoc);
18989 ServiceCallingLocsList.push_back(HString +
'-' + VString);
19012 else if(AVE.
Command ==
"cdt")
19025 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
19034 ServiceCallingLocsList.push_back(LName);
19038 int HLoc = TE.
HLoc;
19039 int VLoc = TE.
VLoc;
19040 AnsiString HString;
19041 AnsiString VString;
19044 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19048 HString = AnsiString(HLoc);
19052 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19056 VString = AnsiString(VLoc);
19058 ServiceCallingLocsList.push_back(HString +
'-' + VString);
19062 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
19066 SequenceLog +=
"2\n";
19095 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
19101 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
19102 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
19103 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
19105 SequenceLog +=
"3\n";
19112 TDateTime LastTDTime;
19113 int IncMinutes = 0;
19115 if(ActionVector.empty())
19119 if(ActionVector.at(0).SignallerControl)
19123 if(AVLast->FormatType ==
Repeat)
19125 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
19133 if(AVLast->ArrivalTime != TDateTime(-1))
19135 LastTDTime = AVLast->ArrivalTime;
19137 else if(AVLast->EventTime != TDateTime(-1))
19139 LastTDTime = AVLast->EventTime;
19158 SequenceLog +=
"4\n";
19195 int IncMinutes = 0;
19197 if(ActionVector.empty())
19201 if(ActionVector.at(0).SignallerControl)
19205 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
19207 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
19209 for(
int y = 0; y < NumTrains; y++)
19223 for(
unsigned int z = 0; z < ActionVector.size(); z++)
19238 LocServiceTimesVector.push_back(TLSTEntry);
19241 AnsiString IncTime =
"", FoundStopTime =
"";
19242 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19244 if(ActionVector.at(a).FormatType ==
TimeLoc)
19255 if(FoundStopTime ==
"")
19257 throw Exception(
"Failure to determine FoundStopTime for located Snt");
19259 int WhileCount = 0;
19268 if(IncTime >= FoundStopTime)
19272 LocServiceTimesVector.push_back(TLSTEntry);
19273 if(WhileCount > 2000)
19275 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
19288 int HLoc = TE.
HLoc;
19289 int VLoc = TE.
VLoc;
19290 AnsiString HString;
19291 AnsiString VString;
19294 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19298 HString = AnsiString(HLoc);
19302 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19306 VString = AnsiString(VLoc);
19308 TLSTEntry.
Location = HString +
'-' + VString;
19312 LocServiceTimesVector.push_back(TLSTEntry);
19320 LocServiceTimesVector.push_back(TLSTEntry);
19322 AnsiString IncTime =
"", FoundStopTime =
"";
19323 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19325 if(ActionVector.at(a).FormatType ==
TimeLoc)
19336 if(FoundStopTime ==
"")
19338 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
19340 int WhileCount = 0;
19349 if(IncTime >= FoundStopTime)
19353 LocServiceTimesVector.push_back(TLSTEntry);
19354 if(WhileCount > 2000)
19356 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
19366 bool SkipAddingMinutes =
false;
19369 LocServiceTimesVector.push_back(TLSTEntry);
19371 AnsiString IncTime =
"", FoundStopTime =
"";
19372 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
19374 if(ActionVector.at(a).FormatType ==
TimeLoc)
19382 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
19386 LocServiceTimesVector.pop_back();
19387 SkipAddingMinutes =
true;
19392 if(FoundStopTime ==
"")
19394 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
19396 if(!SkipAddingMinutes)
19398 int WhileCount = 0;
19407 if(IncTime >= FoundStopTime)
19411 LocServiceTimesVector.push_back(TLSTEntry);
19412 if(WhileCount > 2000)
19414 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
19423 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
19425 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
19427 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
19428 LocServiceTimesVector.pop_back();
19429 LocServiceTimesVector.push_back(TLSTEntry);
19434 LocServiceTimesVector.push_back(TLSTEntry);
19440 LocServiceTimesVector.push_back(TLSTEntry);
19459 LocServiceTimesVector.push_back(TLSTEntry);
19463 AnsiString TempDepTime = TLSTEntry.
DepTime;
19465 LocServiceTimesVector.push_back(TLSTEntry);
19467 while(TLSTEntry.
AtLocTime < TempDepTime)
19472 TLSTEntry.
DepTime = TempDepTime;
19473 LocServiceTimesVector.push_back(TLSTEntry);
19477 LocServiceTimesVector.push_back(TLSTEntry);
19488 LocServiceTimesVector.push_back(TLSTEntry);
19491 LocServiceTimesVector.push_back(TLSTEntry);
19511 AnsiString HString;
19512 AnsiString VString;
19515 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
19519 HString = AnsiString(HLoc);
19523 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
19527 VString = AnsiString(VLoc);
19529 TLSTEntry.
Location = HString +
'-' + VString;
19531 LocServiceTimesVector.push_back(TLSTEntry);
19536 AnsiString FrhTime;
19537 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
19541 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
19549 LocServiceTimesVector.push_back(TLSTEntry);
19555 LocServiceTimesVector.push_back(TLSTEntry);
19560 else if(AVE.
Command ==
"Frh-sh")
19562 if(y == NumTrains - 1)
19568 LocServiceTimesVector.push_back(TLSTEntry);
19574 LocServiceTimesVector.push_back(TLSTEntry);
19587 SequenceLog +=
"5\n";
19620 TLocServiceTimesVector::iterator Ptr1, Ptr2;
19623 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
19624 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
19626 std::ofstream TTFile3(TTFileName3.c_str());
19630 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
19634 if(LocServiceTimesVector.empty())
19636 ShowMessage(
"No timetabled services found");
19638 DeleteFile(TTFileName3);
19642 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
19643 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
19644 SequenceLog +=
"6\n";
19873 Ptr1 = LocServiceTimesVector.begin();
19875 while(Ptr2 != LocServiceTimesVector.end())
19877 while(Ptr2->Location == Ptr1->Location)
19880 if(Ptr2 == LocServiceTimesVector.end())
19887 if(Ptr2 != LocServiceTimesVector.end())
19895 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19896 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19897 MinuteString =
" minutes";
19898 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19901 MinuteString =
" minute";
19903 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19904 TTFile3 <<
",Platforms,Trains\n\n";
19906 Ptr1 = LocServiceTimesVector.begin();
19908 while(Ptr2 != LocServiceTimesVector.end())
19910 PreviousService =
"";
19911 NumTrainsAtLoc = 0;
19912 ServiceAndRepeatNumTotal =
"";
19914 NumPlatsAtThisLocCalculated =
false;
19916 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19918 PreviousService =
"";
19919 NumTrainsAtLoc = 0;
19920 ServiceAndRepeatNumTotal =
"";
19922 NumPlatsAtThisLocCalculated =
false;
19926 if(Ptr2 == LocServiceTimesVector.end())
19931 if(Ptr2 == LocServiceTimesVector.end())
19935 while(Ptr2->Location == Ptr1->Location)
19937 PreviousService =
"";
19938 NumTrainsAtLoc = 0;
19939 ServiceAndRepeatNumTotal =
"";
19940 BasicTime = Ptr1->ArrTime;
19941 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19945 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19947 BasicTime = Ptr2->ArrTime;
19950 if(Ptr2 == LocServiceTimesVector.end())
19954 if(Ptr2->Location != Ptr1->Location)
19959 if(Ptr2 == LocServiceTimesVector.end())
19963 if(Ptr2->Location != Ptr1->Location)
19969 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19973 if(!NumPlatsAtThisLocCalculated)
19976 NumPlatsAtThisLocCalculated =
true;
19978 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19980 if(ServiceAndRepeatNumTotal ==
"")
19982 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19983 NumTrainsAtLoc = 1;
19987 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19990 PreviousService = Ptr2->ServiceAndRepeatNum;
19991 if(ServiceAndRepeatNumTotal ==
"")
19993 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19994 NumTrainsAtLoc = 1;
19998 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
20002 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
20004 int MaxNumberOfSameDirections = 0;
20005 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
20010 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
20014 AnsiString Asterisk =
"";
20015 if(MaxNumberOfSameDirections >= NumPlats)
20020 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
20021 ArrivalsPrinted =
true;
20022 ServiceAndRepeatNumTotal =
"";
20024 if(Ptr2 == LocServiceTimesVector.end())
20028 if(Ptr2->Location != Ptr1->Location)
20033 if(Ptr2 == LocServiceTimesVector.end())
20039 if(!ArrivalsPrinted)
20041 TTFile3 <<
"Nothing to report for arrivals";
20046 SequenceLog +=
"7\n";
20051 Ptr1 = LocServiceTimesVector.begin();
20053 while(Ptr2 != LocServiceTimesVector.end())
20055 while(Ptr2->Location == Ptr1->Location)
20058 if(Ptr2 == LocServiceTimesVector.end())
20065 if(Ptr2 != LocServiceTimesVector.end())
20072 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
20073 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
20074 MinuteString =
" minutes";
20075 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
20078 MinuteString =
" minute";
20080 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
20081 TTFile3 <<
",Platforms,Trains\n\n";
20083 Ptr1 = LocServiceTimesVector.begin();
20085 while(Ptr2 != LocServiceTimesVector.end())
20087 PreviousService =
"";
20088 NumTrainsAtLoc = 0;
20089 ServiceAndRepeatNumTotal =
"";
20091 NumPlatsAtThisLocCalculated =
false;
20093 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
20095 PreviousService =
"";
20096 NumTrainsAtLoc = 0;
20097 ServiceAndRepeatNumTotal =
"";
20099 NumPlatsAtThisLocCalculated =
false;
20103 if(Ptr2 == LocServiceTimesVector.end())
20108 if(Ptr2 == LocServiceTimesVector.end())
20112 while(Ptr2->Location == Ptr1->Location)
20114 PreviousService =
"";
20115 NumTrainsAtLoc = 0;
20116 ServiceAndRepeatNumTotal =
"";
20117 BasicTime = Ptr1->DepTime;
20118 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
20122 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
20124 BasicTime = Ptr2->DepTime;
20127 if(Ptr2 == LocServiceTimesVector.end())
20131 if(Ptr2->Location != Ptr1->Location)
20136 if(Ptr2 == LocServiceTimesVector.end())
20140 if(Ptr2->Location != Ptr1->Location)
20146 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
20150 if(!NumPlatsAtThisLocCalculated)
20153 NumPlatsAtThisLocCalculated =
true;
20155 if(Ptr1->ServiceAndRepeatNum != PreviousService)
20157 if(ServiceAndRepeatNumTotal ==
"")
20159 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
20160 NumTrainsAtLoc = 1;
20164 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
20167 PreviousService = Ptr2->ServiceAndRepeatNum;
20168 if(ServiceAndRepeatNumTotal ==
"")
20170 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
20171 NumTrainsAtLoc = 1;
20175 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
20179 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
20181 int MaxNumberOfSameDirections = 0;
20182 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
20187 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
20191 AnsiString Asterisk =
"";
20192 if(MaxNumberOfSameDirections >= NumPlats)
20197 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
20198 DeparturesPrinted =
true;
20199 ServiceAndRepeatNumTotal =
"";
20201 if(Ptr2 == LocServiceTimesVector.end())
20205 if(Ptr2->Location != Ptr1->Location)
20210 if(Ptr2 == LocServiceTimesVector.end())
20216 if(!DeparturesPrinted)
20218 TTFile3 <<
"Nothing to report for departures";
20223 SequenceLog +=
"8\n";
20230 Ptr1 = LocServiceTimesVector.begin();
20232 while(Ptr2 != LocServiceTimesVector.end())
20234 while(Ptr2->Location == Ptr1->Location)
20237 if(Ptr2 == LocServiceTimesVector.end())
20244 if(Ptr2 != LocServiceTimesVector.end())
20251 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
20252 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
20253 TTFile3 <<
",Platforms,Trains,\n\n";
20254 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
20255 Ptr1 = LocServiceTimesVector.begin();
20257 while(Ptr2 != LocServiceTimesVector.end())
20259 PreviousService =
"";
20260 ServiceAndRepeatNumTotal =
"";
20261 NumTrainsAtLoc = 0;
20263 NumPlatsAtThisLocCalculated =
false;
20266 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
20268 PreviousService =
"";
20269 ServiceAndRepeatNumTotal =
"";
20270 NumTrainsAtLoc = 0;
20272 NumPlatsAtThisLocCalculated =
false;
20276 if(Ptr2 == LocServiceTimesVector.end())
20281 if(Ptr2 == LocServiceTimesVector.end())
20285 while(Ptr2->Location == Ptr1->Location)
20287 if(Ptr1->FrhMarker ==
"Frh")
20290 Ptr1->FrhMarker =
"FrhCounted";
20292 PreviousService =
"";
20293 NumTrainsAtLoc = 0;
20294 ServiceAndRepeatNumTotal =
"";
20295 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
20299 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
20302 if(Ptr1->FrhMarker ==
"Frh")
20305 Ptr1->FrhMarker =
"FrhCounted";
20308 if(Ptr2 == LocServiceTimesVector.end())
20312 if(Ptr2->Location != Ptr1->Location)
20317 if(Ptr2 == LocServiceTimesVector.end())
20321 if(Ptr2->Location != Ptr1->Location)
20325 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
20327 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
20331 if(!NumPlatsAtThisLocCalculated)
20334 NumPlatsAtThisLocCalculated =
true;
20336 if(Ptr1->ServiceAndRepeatNum != PreviousService)
20338 if(ServiceAndRepeatNumTotal ==
"")
20340 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
20341 NumTrainsAtLoc = 1;
20345 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
20348 PreviousService = Ptr2->ServiceAndRepeatNum;
20349 if(ServiceAndRepeatNumTotal ==
"")
20351 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
20352 NumTrainsAtLoc = 1;
20356 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
20359 if(Ptr1->FrhMarker ==
"Frh")
20362 Ptr1->FrhMarker =
"FrhCounted";
20365 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
20369 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
20371 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
20373 AnsiString Asterisk =
"";
20374 if(NumTrainsAtLoc > NumPlats)
20381 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
20383 else if(FrhCount == 1)
20385 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
20389 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
20391 LastFrhCount = FrhCount;
20392 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
20393 AtLocsPrinted =
true;
20394 ServiceAndRepeatNumTotal =
"";
20397 if(Ptr2 == LocServiceTimesVector.end())
20401 if(Ptr2->Location != Ptr1->Location)
20406 if(Ptr2 == LocServiceTimesVector.end())
20414 TTFile3 <<
"Nothing to report for trains at locations";
20419 SequenceLog +=
"9\n";
20453 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
20458 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
20467 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20469 SingleServiceEntry = TDE;
20471 for(
unsigned int y = 0; y < SSAV.size(); y++)
20473 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
20475 SingleServiceVector.push_back(SingleServiceEntry);
20478 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
20480 PartServiceEntry = TDE;
20482 for(
unsigned int z = 0; z <= y; z++)
20487 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
20488 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
20491 PartServiceVector.push_back(PartServiceEntry);
20492 if(SSAV.at(y).Command ==
"fsp")
20494 SSAV.at(y).Command =
"Front split - original service continues below";
20495 SSAV.at(y).OtherHeadCode =
"";
20497 if(SSAV.at(y).Command ==
"rsp")
20499 SSAV.at(y).Command =
"Rear split - original service continues below";
20500 SSAV.at(y).OtherHeadCode =
"";
20504 else if(SSAV.at(y).Command ==
"Fns")
20506 SSAV.at(y).Command =
"chr-Fns";
20507 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20508 PartServiceVector.push_back(SingleServiceEntry);
20511 else if(SSAV.at(y).Command ==
"Fns-sh")
20513 SSAV.at(y).Command =
"chr-Fns-sh";
20514 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20515 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20516 PartServiceVector.push_back(SingleServiceEntry);
20519 else if(SSAV.at(y).Command ==
"F-nshs")
20521 SSAV.at(y).Command =
"chr-F-nshs";
20522 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
20523 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20524 PartServiceVector.push_back(SingleServiceEntry);
20530 SequenceLog +=
"10\n";
20534 AnsiString NextRef;
20535 while(!PartServiceVector.empty())
20537 PartServiceEntry = PartServiceVector.at(0);
20538 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
20540 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
20542 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
20546 bool FinishType =
true, FoundFlag =
false;
20553 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
20557 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20561 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20567 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20568 SingleServiceVector.push_back(PartServiceVector.at(0));
20569 PartServiceVector.erase(PartServiceVector.begin());
20574 NewPartServiceEntry = PartServiceVector.at(0);
20578 PartServiceVector.push_back(NewPartServiceEntry);
20581 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
20586 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
20589 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20591 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
20594 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20596 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20599 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
20602 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20603 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20604 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
20605 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20608 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
20612 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
20613 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
20614 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
20622 SequenceLog += +
"11\n";
20623 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
20627 if(!PartServiceVector.empty())
20629 SequenceLog +=
"12\n";
20630 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
20632 SequenceLog +=
"13\n";
20681 bool BufferFacingUnReportedFlag =
true;
20682 bool TrainFacingBuffersReported =
false;
20683 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20689 SequenceLog +=
"13a\n";
20690 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
20693 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
20695 bool BufferFlag =
false;
20696 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
20697 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
20698 AnsiString FrontLocName = AV.at(0).LocationName;
20699 int NextEntryPos, NextExitPos;
20702 if(ThisElement.
Conn[0] == RearTVPos)
20706 else if(ThisElement.
Conn[1] == RearTVPos)
20710 else if(ThisElement.
Conn[2] == RearTVPos)
20714 else if(ThisElement.
Conn[3] == RearTVPos)
20726 if(ThisElement.
Conn[ThisExitPos] == -1)
20728 SequenceLog =
"13b\n";
20729 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
20732 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
20733 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
20735 BufferFlag =
false;
20740 BufferFlag =
false;
20745 BufferFlag =
false;
20753 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
20755 ThisElement = NextElement;
20761 if(NextEntryPos == 0)
20765 else if(NextEntryPos == 1)
20769 else if(NextEntryPos == 2)
20773 else if(NextEntryPos == 3)
20778 ThisElement = NextElement;
20779 ThisExitPos = NextExitPos;
20784 if(BufferFacingUnReportedFlag)
20786 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
20787 BufferFacingUnReportedFlag =
false;
20789 if(AV.at(1).Command !=
"cdt")
20791 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
20792 TrainFacingBuffersReported =
true;
20797 if(!TrainFacingBuffersReported)
20799 TTFile3 <<
"Nothing to report for train facing directions\n\n";
20805 SequenceLog +=
"13c\n";
20808 AnsiString LocationNameToBeChecked =
"";
20809 bool MissingcdtUnreportedFlag =
true;
20811 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20814 unsigned int y = 0;
20815 int FirstInstance = 9999, SecondInstance = 9999;
20816 bool FullBreak =
false;
20817 MarkerList.clear();
20819 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
20828 LocationNameToBeChecked =
"";
20834 if(LocationNameToBeChecked ==
"")
20841 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
20844 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
20849 (AVEntry.
Command ==
"Frh-sh"))
20864 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
20866 AnsiString LocationName;
20873 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
20878 LocationName = TDEntry.
ActionVector.at(a).LocationName;
20880 if(LocationName == LocationNameToBeChecked)
20882 SecondInstance = a;
20884 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20886 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20888 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20891 if(MissingcdtUnreportedFlag)
20893 TTFile3 <<
"Possibly missing changes of direction - these should be checked to see if there is a good reason for cdt's not being included. :-\n\n";
20895 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
20896 MarkerList.push_back(FirstInstance);
20897 MarkerList.push_back(SecondInstance);
20899 MissingcdtUnreportedFlag =
false;
20910 if(MissingcdtUnreportedFlag)
20912 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20918 SequenceLog +=
"14\n";
20927 typedef std::list<AnsiString> TLocList;
20928 TLocList BackwardList, ForwardList;
20929 bool IntroLineNeeded =
true;
20930 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20932 unsigned int cdtPosition = 9999;
20933 AnsiString cdtLocation =
"";
20934 bool FoundSameName =
false;
20935 bool FerEntry =
false;
20936 MarkerList.clear();
20938 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20945 BackwardList.clear();
20946 ForwardList.clear();
20947 bool ValidEnd =
false;
20953 (AVEntry.
Command ==
"Frh-sh"))
20958 if(FerEntry || ValidEnd)
20960 if(MarkerList.empty())
20967 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20969 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20971 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20975 if(IntroLineNeeded)
20977 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20978 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20979 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20980 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20981 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20982 IntroLineNeeded =
false;
20984 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20999 for(
int z = y - 1; z >= 0; z--)
21002 if(AVEntry2.
Command ==
"cdt")
21006 AnsiString LocName =
"";
21016 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
21018 BackwardList.push_back(LocName);
21021 BackwardList.sort();
21022 BackwardList.unique();
21023 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
21032 AnsiString LocName =
"";
21033 if(AVEntry3.
Command ==
"Fer")
21035 int ExitLoc = AVEntry3.
ExitList.front();
21043 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
21045 ForwardList.push_back(LocName);
21048 ForwardList.sort();
21049 ForwardList.unique();
21050 FoundSameName =
false;
21052 if(!BackwardList.empty() && !ForwardList.empty())
21054 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
21056 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
21060 FoundSameName =
true;
21067 MarkerList.push_back(cdtPosition);
21072 if(IntroLineNeeded)
21074 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
21092 SequenceLog +=
"15\n";
21098 catch(
const Exception &e)
21100 AnsiString TTErrorFileName =
"Analysis Error.txt";
21101 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
21102 std::ofstream TTError(TTErrorFileName.c_str());
21105 ShowMessage(
"Analysis error file failed to open - can't be created");
21109 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
21110 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
21111 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
21114 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
21124 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
21126 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
21128 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
21130 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
21131 AnsiString Marker =
"";
21132 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
21135 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
21137 if(
int(x) == *MLIt)
21167 if(AVE.
Command.SubString(1,3) ==
"chr")
21176 AVE.
Command =
"Change of service to ";
21178 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
21180 AVE.
Command =
"Change to shuttle finishing service";
21182 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
21209 AnsiString ListOfExits =
"";
21218 VecFile << Marker <<
"Frh" <<
'\n';
21233 for(
unsigned int x = 0; x < Vector.size(); x++)
21236 if(Vector.at(x).ServiceReference == HeadCode)
21238 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
21240 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
21243 FinishType =
false;
21248 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
21251 FinishType =
false;
21256 return(Vector.at(x));
21260 return(Vector.at(Vector.size() - 1));
21269 if((Time1 ==
"") || (Time2 ==
""))
21274 int Mins = Time1.SubString(4,2).ToInt();
21275 int Hours = Time1.SubString(1,2).ToInt();
21276 int Time1Mins = (Hours * 60) + Mins;
21277 Mins = Time2.SubString(4,2).ToInt();
21278 Hours = Time2.SubString(1,2).ToInt();
21279 int Time2Mins = (Hours * 60) + Mins;
21280 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
21292 bool &AnalysisError,
int &MaxNumberOfSameDirections)
21299 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
21301 std::list<AnsiString> ServiceList;
21303 bool EvenComma =
false;
21304 for(
int x = 1; x <= Input.Length(); x++)
21306 TempStr1 = Input[x];
21307 if(TempStr1 == AnsiString(
',') && EvenComma)
21313 TempStr2 += Input[x];
21315 if(TempStr1 == AnsiString(
','))
21317 EvenComma = !EvenComma;
21321 while(TempStr2.Length() > 0)
21323 SCPos = TempStr2.Pos(
';');
21326 OneService = TempStr2.SubString(1, SCPos - 1);
21327 ServiceList.push_back(OneService);
21328 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
21332 ServiceList.push_back(TempStr2);
21336 ServiceList.sort();
21337 ServiceList.unique();
21338 NumTrainsAtLoc = ServiceList.size();
21341 int DirectionMarker = 0;
21343 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
21345 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21347 *SLIt = *SLIt +
"&0";
21349 SLIt3 = ServiceList.end();
21351 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
21352 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
21353 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
21355 MaxNumberOfSameDirections = 0;
21356 int SameDirectionCount = 0;
21358 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
21362 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
21368 CommaPos1 = SLIt1->Pos(
',');
21369 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
21371 SpacePos = ServiceRef1.Pos(
' ');
21375 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
21376 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
21377 if(RepeatInfo1[1] ==
'F')
21383 SpacePos = RepeatInfo1.Pos(
' ');
21384 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
21387 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
21389 AmpersandPos = AnsiTime1.Pos(
'&');
21390 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
21395 throw Exception(
"ASCLIt1 Error in " + Input);
21397 ServiceCallingLocsList1 = ASCLIt1->second;
21398 AmpersandPos = SLIt1->Pos(
'&');
21399 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
21400 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
21402 SameDirectionCount = 1;
21403 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
21405 CommaPos2 = SLIt2->Pos(
',');
21406 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
21408 SpacePos = ServiceRef2.Pos(
' ');
21412 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
21413 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
21414 if(RepeatInfo2[1] ==
'F')
21420 SpacePos = RepeatInfo2.Pos(
' ');
21421 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
21424 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
21426 AmpersandPos = AnsiTime2.Pos(
'&');
21427 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
21432 throw Exception(
"ASCLIt2 Error in " + Input);
21434 ServiceCallingLocsList2 = ASCLIt2->second;
21436 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
21438 int AmpersandPos = SLIt2->Pos(
'&');
21439 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
21440 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
21441 SameDirectionCount++;
21444 if(SameDirectionCount > MaxNumberOfSameDirections)
21446 MaxNumberOfSameDirections = SameDirectionCount;
21451 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
21454 AmpersandPos = SLIt3->Pos(
'&');
21455 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
21456 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
21459 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21462 AmpersandPos = SLIt->Pos(
'&');
21463 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
21464 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
21465 DirectionMarker = DirectionMarkerString.ToInt();
21466 AnsiString DirectionSuffix =
"";
21468 if(DirectionMarker < 27)
21470 c = 64 + DirectionMarker;
21471 DirectionSuffix =
"," + AnsiString(c);
21473 else if(DirectionMarker < 53)
21475 c = 65 + DirectionMarker - 27;
21476 DirectionSuffix =
",A" + AnsiString(c);
21480 DirectionSuffix =
",?";
21482 *SLIt = ServiceWithoutMarker + DirectionSuffix;
21485 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21487 Output = Output + *SLIt +
",";
21489 if(Output.Length() > 0)
21491 Output = Output.SubString(1, Output.Length() - 1);
21497 catch(
const Exception &e)
21499 AnalysisError =
true;
21511 AnsiString InternalInput = Input, Output =
"", OneService =
"";
21513 std::list<AnsiString> ServiceList;
21515 while(InternalInput.Length() > 0)
21517 CommaPos = InternalInput.Pos(
',');
21520 OneService = InternalInput.SubString(1, CommaPos - 1);
21521 ServiceList.push_back(OneService);
21522 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
21526 ServiceList.push_back(InternalInput);
21527 InternalInput =
"";
21531 ServiceList.sort();
21532 ServiceList.unique();
21533 NumTrainsAtLoc = ServiceList.size();
21534 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
21536 Output = Output + *SLIt +
",";
21538 if(Output.Length() > 0)
21540 Output = Output.SubString(1, Output.Length() - 1);
21553 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
21555 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
21560 bool LocFound =
false;
21561 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
21563 TDateTime FirstServiceTime;
21566 int Ref1Target = 0, Ref1Count = 0;
21567 int Ref2Target = 0, Ref2Count = 0;
21585 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
21588 if((*ListPtr1) == Location)
21590 LocPtr1 = ListPtr1;
21593 if(ListPtr1->SubString(1, 3) ==
"%%%")
21595 AnsiString CDTTime = ListPtr1->SubString(4, 5);
21600 FirstServiceTime = TDateTime(-1);
21601 bool BreakFlag =
false;
21604 if(TDVIt->ServiceReference == Ref1)
21606 if(Ref1Target > Ref1Count)
21611 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21612 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21616 FirstServiceTime = AVIt->EventTime;
21622 FirstServiceTime = AVIt->ArrivalTime;
21628 FirstServiceTime = AVIt->DepartureTime;
21639 if(IncMinutes == -1)
21641 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21643 if(FirstServiceTime == TDateTime(-1))
21645 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21649 if(!Arrival && (Time1 == CDTTime))
21654 if(Arrival && (Time1 == CDTTime))
21658 if(Time1 > CDTTime)
21663 if(Time1 < CDTTime)
21676 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
21678 if((*ListPtr2) == Location)
21680 LocPtr2 = ListPtr2;
21683 if(ListPtr2->SubString(1, 3) ==
"%%%")
21685 AnsiString CDTTime = ListPtr2->SubString(4, 5);
21690 FirstServiceTime = TDateTime(-1);
21691 bool BreakFlag =
false;
21694 if(TDVIt->ServiceReference == Ref2)
21696 if(Ref2Target > Ref2Count)
21701 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
21702 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
21706 FirstServiceTime = AVIt->EventTime;
21712 FirstServiceTime = AVIt->ArrivalTime;
21718 FirstServiceTime = AVIt->DepartureTime;
21729 if(IncMinutes == -1)
21731 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21733 if(FirstServiceTime == TDateTime(-1))
21735 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
21739 if(!Arrival && (Time2 == CDTTime))
21744 if(Arrival && (Time2 == CDTTime))
21748 if(Time2 > CDTTime)
21753 if(Time2 < CDTTime)
21768 LP1 = List1.begin();
21770 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
21772 if(ListPtr1 == List1.begin())
21776 if(ListPtr1->SubString(1, 3) ==
"%%%")
21783 LP2 = List2.begin();
21785 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
21787 if(ListPtr2 == List2.begin())
21791 if(ListPtr2->SubString(1, 3) ==
"%%%")
21801 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21803 if(ListPtr1 == LocPtr1)
21807 if(ListPtr1->SubString(1, 3) ==
"%%%")
21811 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21813 if(ListPtr2 == LocPtr2)
21817 if(ListPtr2->SubString(1, 3) ==
"%%%")
21821 if((*ListPtr1) == (*ListPtr2))
21838 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
21840 if(ListPtr1 == List1.end())
21844 if(ListPtr1->SubString(1, 3) ==
"%%%")
21848 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
21850 if(ListPtr2 == List2.end())
21854 if(ListPtr2->SubString(1, 3) ==
"%%%")
21858 if((*ListPtr1) == (*ListPtr2))
21875 if(ExitList.empty())
21881 AnsiString ExitLocList =
"";
21884 unsigned int Counter = 0;
21885 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
21889 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
21891 ExitLocList +=
"\n";
21894 if(StartName ==
"")
21896 if(ExitList.size() == 1)
21900 return(
" at " + ID);
21905 if(ExitList.size() < 4)
21907 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21912 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21917 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21922 if(ExitList.size() < 4)
21924 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21929 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21935 if(ExitList.size() < 4)
21937 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21938 return(
" at " + StartName);
21942 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21943 return(
" at " + StartName);
21983 AnsiString FormatStr =
"####0.0";
21984 AnsiString AvLateArrMins =
"";
21985 AnsiString AvEarlyArrMins =
"";
21986 AnsiString AvLatePassMins =
"";
21987 AnsiString AvEarlyPassMins =
"";
21988 AnsiString AvLateDepMins =
"";
21989 AnsiString AvLateExitMins =
"";
21990 AnsiString AvEarlyExitMins =
"";
21993 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22026 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
22027 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
22039 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
22043 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
22051 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
22055 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
22063 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
22071 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
22075 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
22079 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
22083 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
22087 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
22091 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
22096 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
22100 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
22104 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
22108 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
22112 PerfFile <<
LateExits <<
" late exits" <<
'\n';
22116 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
22120 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
22124 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
22129 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
22133 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
22137 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
22141 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
22145 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
22147 TDateTime TempExcessLCDownTime;
22161 if(TempExcessLCDownTime > TDateTime(0))
22167 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
22171 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
22183 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
22187 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
22223 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
22227 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
22233 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
22237 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
22240 AnsiString AvLateMinsLocsNotReached =
"";
22246 if(LocsNotReached > 0)
22249 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
22253 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
22257 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
22269 PerfFile <<
Derailments <<
" derailments" <<
'\n';
22273 PerfFile <<
Derailments <<
" derailment" <<
'\n';
22283 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
22285 bool DerailSPADFlag =
false, CrashFlag =
false;
22287 int OverallScorePercent = 100;
22288 int TotArrDepExit = 0;
22289 double TotLateMinsFactor = 1;
22290 double MissedStopAndSPADRiskFactor = 1;
22291 double NetNegFactor = 1;
22301 OverallScorePercent = 5;
22302 DerailSPADFlag =
true;
22306 OverallScorePercent = 0;
22309 if(OverallScorePercent == 100)
22314 LatenessPenalty = 0;
22320 if(TotArrDepExit > 0)
22329 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
22331 OverallScorePercent = 100 * NetNegFactor;
22334 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
22337 AnsiString OneFailureString =
", though the failure would account for some poor performance";
22338 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
22339 AnsiString AddedString =
"";
22342 AddedString = OneFailureString;
22346 AddedString = TwoOrMoreFailureString;
22348 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
22349 AnsiString Rating =
"";
22350 if(OverallScorePercent == 100)
22352 Rating =
"Perfect!";
22354 else if(OverallScorePercent >= 95)
22356 Rating =
"Excellent";
22358 else if(OverallScorePercent >= 90)
22360 Rating =
"Very good";
22362 else if(OverallScorePercent >= 80)
22366 else if(OverallScorePercent >= 70)
22370 else if(OverallScorePercent >= 60)
22372 Rating =
"Unacceptable" + AddedString;
22374 else if(OverallScorePercent >= 50)
22376 Rating =
"Poor" + AddedString;
22378 else if(OverallScorePercent >= 40)
22380 Rating =
"Bad" + AddedString;
22382 else if(OverallScorePercent >= 30)
22384 Rating =
"Very bad" + AddedString;
22386 else if(OverallScorePercent >= 20)
22388 Rating =
"Terrible" + AddedString;
22390 else if(OverallScorePercent >= 10)
22392 Rating =
"Appalling" + AddedString;
22394 else if(OverallScorePercent >= 5)
22398 Rating =
"Disastrous - potential loss of life";
22403 Rating =
"Dire" + AddedString;
22406 else if(OverallScorePercent < 5)
22410 Rating =
"Catastrophic - loss of life";
22414 Rating =
"Abysmal";
22417 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
22421 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
22423 PerfFile <<
'\n' <<
"***************************************";
22433 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22483 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22518 int IncrementalMinutes = 0;
22532 bool TrainOperatingFlag =
false;
22537 TrainOperatingFlag =
true;
22541 if(TrainOperatingFlag)
22549 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
22596 AnsiString HeadCode;
22600 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22604 HCandTrainPosParam.first = HeadCode;
22605 HCandTrainPosParam.second = TrainID;
22607 if((TimeToAct >= 0) && (TimeToAct < 59.9))
22610 OpTimeToActMultiMapEntry.first = TimeToAct;
22611 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22640 float TimeToAct = 0;
22641 int DistanceToRedSignal = 0;
22644 ContinuationEntryVecPosVector.clear();
22645 bool LaterTrain =
false;
22649 LaterTrain =
false;
22650 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
22661 if(!ContinuationEntryVecPosVector.empty())
22663 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
22665 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
22679 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
22680 AnsiString HeadCode = CTEIt->second.HeadCode;
22681 float CurrentStopTime;
22682 float LaterStopTime;
22683 float RecoverableTime;
22686 int DistanceToExit;
22688 bool SigControlAndCanPassRedSignal =
false;
22696 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
22702 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
22703 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
22706 if(AvTrackSpeed < 30)
22710 if(DistanceToRedSignal == -1)
22716 int Speed = AvTrackSpeed;
22717 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
22718 if(AvTrackSpeed > MaxSpeed)
22722 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
22725 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
22728 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
22733 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
22734 TimeToAct += MinsBefEnter;
22737 HCandTrainPosParam.first = HeadCode;
22738 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
22741 if(TimeToAct < 59.9)
22743 OpTimeToActMultiMapEntry.first = TimeToAct;
22744 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
22769 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
22779 TimeToExitMultiMapEntry.first = ExitPair;
22780 TimeToExitMultiMapEntry.second = ExitInfo;
22790 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
22791 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
22800 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
22801 int DistanceToRedSignal = 0;
22802 DistanceToExit = -1;
22803 ExitPair.first = -1;
22804 ExitPair.second = -1;
22805 int CumTrackSpeed = 0;
22807 int TrackSpeedCount = 0;
22808 float KmPerLocationStop;
22809 float MaxAllowableSpeed;
22819 int CurrentElement = TrackVectorPosition;
22820 int CurrentEntryPos = TrackVectorPositionEntryPos;
22825 CurrentStopTime = 0;
22827 RecoverableTime = 0;
22828 if(CurrentElement == -1)
22833 int CurrentExitPos;
22838 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
22842 CurrentExitPos = 1;
22846 CurrentExitPos = 3;
22851 CurrentExitPos = 0;
22891 TimeToDepart+= 0.5;
22893 if(TimeToDepart < 0.5)
22895 TimeToDepart = 0.5;
22898 CurrentStopTime = float(TimeToDepart);
22906 CurrentStopTime = float(TimeToDepart);
22917 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22928 else if(SigControlAndCanPassRedSignal)
22933 if((NextEntryPos == 0) || (NextEntryPos == 2))
22954 CurrentElement = NextElement;
22955 CurrentEntryPos = NextEntryPos;
22956 CurrentExitPos = NextExitPos;
22968 int LaterStopNumber = 0;
22972 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22981 if(CurrentEntryPos > 1)
22996 DistanceToExit = DistanceToRedSignal;
23001 if(TrackSpeedCount > 0)
23003 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
23007 if(CurrentEntryPos > 1)
23018 if(LaterStopNumber > 0)
23020 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
23021 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
23027 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
23031 if(AvTrackSpeed > MaxAllowableSpeed)
23033 AvTrackSpeed = MaxAllowableSpeed;
23045 bool StopRequired =
false;
23064 int TrainOnElement;
23071 if(CurrentEntryPos > 1)
23080 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
23089 double StopTimeDouble;
23102 if(StopTimeDouble < 0.5)
23104 StopTimeDouble = 0.5;
23108 LaterStopTime += float(StopTimeDouble);
23109 RecoverableTime += StopTimeDouble - 0.5;
23110 if((LaterStopNumber == 1) && (TrainID > -1))
23118 if((AVPtr + 1)->FormatType ==
TimeLoc)
23122 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
23133 if(StopTimeDouble < 0.5)
23135 StopTimeDouble = 0.5;
23138 LaterStopTime += float(StopTimeDouble);
23139 RecoverableTime += StopTimeDouble - 0.5;
23140 if((LaterStopNumber == 1) && (TrainID > -1))
23150 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
23161 if(StopTimeDouble < 0.5)
23163 StopTimeDouble = 0.5;
23166 LaterStopTime += float(StopTimeDouble);
23167 RecoverableTime += StopTimeDouble - 0.5;
23168 if((LaterStopNumber == 1) && (TrainID > -1))
23185 if(NextElement == -1)
23194 if((NextEntryPos == 0) || (NextEntryPos == 2))
23215 CurrentElement = NextElement;
23216 CurrentEntryPos = NextEntryPos;
23217 CurrentExitPos = NextExitPos;
23222 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
23235 if(TrackSpeedCount > 0)
23237 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
23241 if(CurrentEntryPos > 1)
23252 if(LaterStopNumber > 0)
23254 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
23255 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
23261 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
23265 if(AvTrackSpeed > MaxAllowableSpeed)
23267 AvTrackSpeed = MaxAllowableSpeed;
23270 return(DistanceToRedSignal);